MdeModulePkg Variable: Merge from Auth Variable driver in SecurityPkg

What to do:
1. Merge from Auth Variable driver in SecurityPkg to Variable drive in
MdeModulePkg. Then the merged Variable driver in MdeModulePkg will
link to AuthVariableLib and TpmMeasurementLib.
AuthVariableLibNull and TpmMeasurementLibNull in MdeModulePkg
could be used for non auth variable support.
AuthVariableLib and DxeTpmMeasurementLib in SecurityPkg
may be used for auth variable support.

Why to do:
1. Remove code duplication and reduce maintenance effort.
After auth variable service separated from Auth Variable driver in SecurityPkg
to AuthVariableLib. The remaining code logic of Auth Variable driver in SecurityPkg
will be almost same with Variable driver in MdeModulePkg. Now it is to
merge them.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17765 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Star Zeng
2015-07-01 03:08:29 +00:00
committed by lzeng14
parent c88c267d65
commit fa0737a839
16 changed files with 2357 additions and 696 deletions
+21 -15
View File
@@ -2,12 +2,12 @@
The file defined some common structures used for communicating between SMM variable module and SMM variable wrapper module.
Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution.
This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution.
The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
@@ -23,8 +23,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
extern EFI_GUID gSmmVariableWriteGuid;
//
// This structure is used for SMM variable. the collected statistics data is saved in SMRAM. It can be got from
// SMI handler. The communication buffer should be:
// This structure is used for SMM variable. the collected statistics data is saved in SMRAM. It can be got from
// SMI handler. The communication buffer should be:
// EFI_SMM_COMMUNICATE_HEADER + SMM_VARIABLE_COMMUNICATE_HEADER + payload.
//
typedef struct {
@@ -39,26 +39,26 @@ typedef struct {
#define SMM_VARIABLE_FUNCTION_GET_VARIABLE 1
//
// The payload for this function is SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME.
//
//
#define SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME 2
//
// The payload for this function is SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE.
//
//
#define SMM_VARIABLE_FUNCTION_SET_VARIABLE 3
//
// The payload for this function is SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO.
//
//
#define SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO 4
//
// It is a notify event, no extra payload for this function.
//
//
#define SMM_VARIABLE_FUNCTION_READY_TO_BOOT 5
//
// It is a notify event, no extra payload for this function.
//
//
#define SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE 6
//
// The payload for this function is VARIABLE_INFO_ENTRY. The GUID in EFI_SMM_COMMUNICATE_HEADER
// The payload for this function is VARIABLE_INFO_ENTRY. The GUID in EFI_SMM_COMMUNICATE_HEADER
// is gEfiSmmVariableProtocolGuid.
//
#define SMM_VARIABLE_FUNCTION_GET_STATISTICS 7
@@ -71,6 +71,8 @@ typedef struct {
#define SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_GET 10
#define SMM_VARIABLE_FUNCTION_GET_PAYLOAD_SIZE 11
///
/// Size of SMM communicate header, without including the payload.
///
@@ -88,7 +90,7 @@ typedef struct {
EFI_GUID Guid;
UINTN DataSize;
UINTN NameSize;
UINT32 Attributes;
UINT32 Attributes;
CHAR16 Name[1];
} SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE;
@@ -108,7 +110,7 @@ typedef struct {
UINT64 MaximumVariableStorageSize;
UINT64 RemainingVariableStorageSize;
UINT64 MaximumVariableSize;
UINT32 Attributes;
UINT32 Attributes;
} SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO;
typedef SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE;
@@ -120,4 +122,8 @@ typedef struct {
CHAR16 Name[1];
} SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY;
#endif // _SMM_VARIABLE_COMMON_H_
typedef struct {
UINTN VariablePayloadSize;
} SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE;
#endif // _SMM_VARIABLE_COMMON_H_
@@ -0,0 +1,255 @@
/** @file
Measure TrEE required variable.
Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
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
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <PiDxe.h>
#include <Guid/ImageAuthentication.h>
#include <IndustryStandard/UefiTcgPlatform.h>
#include <Protocol/TrEEProtocol.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseLib.h>
#include <Library/TpmMeasurementLib.h>
typedef struct {
CHAR16 *VariableName;
EFI_GUID *VendorGuid;
} VARIABLE_TYPE;
VARIABLE_TYPE mVariableType[] = {
{EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid},
{EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid},
{EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid},
{EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid},
{EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid},
};
/**
This function will return if this variable is SecureBootPolicy Variable.
@param[in] VariableName A Null-terminated string that is the name of the vendor's variable.
@param[in] VendorGuid A unique identifier for the vendor.
@retval TRUE This is SecureBootPolicy Variable
@retval FALSE This is not SecureBootPolicy Variable
**/
BOOLEAN
IsSecureBootPolicyVariable (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid
)
{
UINTN Index;
for (Index = 0; Index < sizeof(mVariableType)/sizeof(mVariableType[0]); Index++) {
if ((StrCmp (VariableName, mVariableType[Index].VariableName) == 0) &&
(CompareGuid (VendorGuid, mVariableType[Index].VendorGuid))) {
return TRUE;
}
}
return FALSE;
}
/**
Measure and log an EFI variable, and extend the measurement result into a specific PCR.
@param[in] VarName A Null-terminated string that is the name of the vendor's variable.
@param[in] VendorGuid A unique identifier for the vendor.
@param[in] VarData The content of the variable data.
@param[in] VarSize The size of the variable data.
@retval EFI_SUCCESS Operation completed successfully.
@retval EFI_OUT_OF_RESOURCES Out of memory.
@retval EFI_DEVICE_ERROR The operation was unsuccessful.
**/
EFI_STATUS
EFIAPI
MeasureVariable (
IN CHAR16 *VarName,
IN EFI_GUID *VendorGuid,
IN VOID *VarData,
IN UINTN VarSize
)
{
EFI_STATUS Status;
UINTN VarNameLength;
EFI_VARIABLE_DATA_TREE *VarLog;
UINT32 VarLogSize;
ASSERT ((VarSize == 0 && VarData == NULL) || (VarSize != 0 && VarData != NULL));
VarNameLength = StrLen (VarName);
VarLogSize = (UINT32)(sizeof (*VarLog) + VarNameLength * sizeof (*VarName) + VarSize
- sizeof (VarLog->UnicodeName) - sizeof (VarLog->VariableData));
VarLog = (EFI_VARIABLE_DATA_TREE *) AllocateZeroPool (VarLogSize);
if (VarLog == NULL) {
return EFI_OUT_OF_RESOURCES;
}
CopyMem (&VarLog->VariableName, VendorGuid, sizeof(VarLog->VariableName));
VarLog->UnicodeNameLength = VarNameLength;
VarLog->VariableDataLength = VarSize;
CopyMem (
VarLog->UnicodeName,
VarName,
VarNameLength * sizeof (*VarName)
);
if (VarSize != 0) {
CopyMem (
(CHAR16 *)VarLog->UnicodeName + VarNameLength,
VarData,
VarSize
);
}
DEBUG ((EFI_D_INFO, "AuthVariableDxe: MeasureVariable (Pcr - %x, EventType - %x, ", (UINTN)7, (UINTN)EV_EFI_VARIABLE_AUTHORITY));
DEBUG ((EFI_D_INFO, "VariableName - %s, VendorGuid - %g)\n", VarName, VendorGuid));
Status = TpmMeasureAndLogData (
7,
EV_EFI_VARIABLE_DRIVER_CONFIG,
VarLog,
VarLogSize,
VarLog,
VarLogSize
);
FreePool (VarLog);
return Status;
}
/**
Returns the status whether get the variable success. The function retrieves
variable through the UEFI Runtime Service GetVariable(). The
returned buffer is allocated using AllocatePool(). The caller is responsible
for freeing this buffer with FreePool().
This API is only invoked in boot time. It may NOT be invoked at runtime.
@param[in] Name The pointer to a Null-terminated Unicode string.
@param[in] Guid The pointer to an EFI_GUID structure
@param[out] Value The buffer point saved the variable info.
@param[out] Size The buffer size of the variable.
@return EFI_OUT_OF_RESOURCES Allocate buffer failed.
@return EFI_SUCCESS Find the specified variable.
@return Others Errors Return errors from call to gRT->GetVariable.
**/
EFI_STATUS
InternalGetVariable (
IN CONST CHAR16 *Name,
IN CONST EFI_GUID *Guid,
OUT VOID **Value,
OUT UINTN *Size
)
{
EFI_STATUS Status;
UINTN BufferSize;
//
// Try to get the variable size.
//
BufferSize = 0;
*Value = NULL;
if (Size != NULL) {
*Size = 0;
}
Status = gRT->GetVariable ((CHAR16 *) Name, (EFI_GUID *) Guid, NULL, &BufferSize, *Value);
if (Status != EFI_BUFFER_TOO_SMALL) {
return Status;
}
//
// Allocate buffer to get the variable.
//
*Value = AllocatePool (BufferSize);
ASSERT (*Value != NULL);
if (*Value == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Get the variable data.
//
Status = gRT->GetVariable ((CHAR16 *) Name, (EFI_GUID *) Guid, NULL, &BufferSize, *Value);
if (EFI_ERROR (Status)) {
FreePool(*Value);
*Value = NULL;
}
if (Size != NULL) {
*Size = BufferSize;
}
return Status;
}
/**
SecureBoot Hook for SetVariable.
@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
)
{
EFI_STATUS Status;
UINTN VariableDataSize;
VOID *VariableData;
if (!IsSecureBootPolicyVariable (VariableName, VendorGuid)) {
return ;
}
//
// We should NOT use Data and DataSize here,because it may include signature,
// or is just partial with append attributes, or is deleted.
// We should GetVariable again, to get full variable content.
//
Status = InternalGetVariable (
VariableName,
VendorGuid,
&VariableData,
&VariableDataSize
);
if (EFI_ERROR (Status)) {
VariableData = NULL;
VariableDataSize = 0;
}
Status = MeasureVariable (
VariableName,
VendorGuid,
VariableData,
VariableDataSize
);
DEBUG ((EFI_D_INFO, "MeasureBootPolicyVariable - %r\n", Status));
if (VariableData != NULL) {
FreePool (VariableData);
}
return ;
}
@@ -1,9 +1,8 @@
/** @file
Handles non-volatile variable store garbage collection, using FTW
(Fault Tolerant Write) protocol.
Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
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
@@ -50,7 +49,7 @@ GetLbaAndOffsetByAddress (
Fvb = NULL;
*Lba = (EFI_LBA) (-1);
*Offset = 0;
//
// Get the proper FVB protocol.
//
@@ -2,12 +2,12 @@
Implementation functions and structures for var check protocol.
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
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
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
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
@@ -616,30 +616,49 @@ UEFI_DEFINED_VARIABLE_ENTRY mGlobalVariableList2[] = {
},
};
typedef struct {
EFI_GUID *Guid;
CHAR16 *Name;
VAR_CHECK_VARIABLE_PROPERTY VariableProperty;
} VARIABLE_DRIVER_VARIABLE_ENTRY;
VARIABLE_DRIVER_VARIABLE_ENTRY mVariableDriverVariableList[] = {
//
// EFI_IMAGE_SECURITY_DATABASE_GUID
//
UEFI_DEFINED_VARIABLE_ENTRY mImageSecurityVariableList[] = {
{
&gEdkiiVarErrorFlagGuid,
VAR_ERROR_FLAG_NAME,
EFI_IMAGE_SECURITY_DATABASE,
{
VAR_CHECK_VARIABLE_PROPERTY_REVISION,
VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY,
VARIABLE_ATTRIBUTE_NV_BS_RT,
sizeof (VAR_ERROR_FLAG),
sizeof (VAR_ERROR_FLAG),
}
0,
VARIABLE_ATTRIBUTE_NV_BS_RT_AT,
1,
MAX_UINTN
},
NULL
},
{
EFI_IMAGE_SECURITY_DATABASE1,
{
VAR_CHECK_VARIABLE_PROPERTY_REVISION,
0,
VARIABLE_ATTRIBUTE_NV_BS_RT_AT,
1,
MAX_UINTN
},
NULL
},
{
EFI_IMAGE_SECURITY_DATABASE2,
{
VAR_CHECK_VARIABLE_PROPERTY_REVISION,
0,
VARIABLE_ATTRIBUTE_NV_BS_RT_AT,
1,
MAX_UINTN
},
NULL
},
};
/**
Get UEFI defined global variable property.
The code will check if variable guid is global variable guid first.
If yes, further check if variable name is in mGlobalVariableList or mGlobalVariableList2.
Get UEFI defined global variable or image security database variable property.
The code will check if variable guid is global variable or image security database guid first.
If yes, further check if variable name is in mGlobalVariableList, mGlobalVariableList2 or mImageSecurityVariableList.
@param[in] VariableName Pointer to variable name.
@param[in] VendorGuid Variable Vendor Guid.
@@ -647,8 +666,8 @@ VARIABLE_DRIVER_VARIABLE_ENTRY mVariableDriverVariableList[] = {
@param[out] VariableProperty Pointer to variable property.
@param[out] VarCheckFunction Pointer to check function.
@retval EFI_SUCCESS Variable is not global variable.
@retval EFI_INVALID_PARAMETER Variable is global variable, but variable name is not in the lists.
@retval EFI_SUCCESS Variable is not global variable or image security database variable.
@retval EFI_INVALID_PARAMETER Variable is global variable or image security database variable, but variable name is not in the lists.
**/
EFI_STATUS
@@ -711,36 +730,24 @@ GetUefiDefinedVariableProperty (
return EFI_INVALID_PARAMETER;
}
//
// It is not global variable.
//
return EFI_SUCCESS;
}
/**
Get variable property for variables managed by Varaible driver.
@param[in] VariableName Pointer to variable name.
@param[in] VendorGuid Variable Vendor Guid.
@return Pointer to variable property.
**/
VAR_CHECK_VARIABLE_PROPERTY *
GetVariableDriverVariableProperty (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid
)
{
UINTN Index;
for (Index = 0; Index < sizeof (mVariableDriverVariableList)/sizeof (mVariableDriverVariableList[0]); Index++) {
if ((CompareGuid (mVariableDriverVariableList[Index].Guid, VendorGuid)) && (StrCmp (mVariableDriverVariableList[Index].Name, VariableName) == 0)) {
return &mVariableDriverVariableList[Index].VariableProperty;
if (CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid)) {
for (Index = 0; Index < sizeof (mImageSecurityVariableList)/sizeof (mImageSecurityVariableList[0]); Index++) {
if (StrCmp (mImageSecurityVariableList[Index].Name, VariableName) == 0) {
if (VarCheckFunction != NULL) {
*VarCheckFunction = mImageSecurityVariableList[Index].CheckFunction;
}
*VariableProperty = &mImageSecurityVariableList[Index].VariableProperty;
return EFI_SUCCESS;
}
}
return EFI_INVALID_PARAMETER;
}
return NULL;
//
// It is not global variable, image security database variable.
//
return EFI_SUCCESS;
}
/**
@@ -799,13 +806,18 @@ InternalVarCheckSetVariableCheck (
break;
}
}
if (Property == NULL) {
Property = GetVariableDriverVariableProperty (VariableName, VendorGuid);
}
if (Property == NULL) {
Status = GetUefiDefinedVariableProperty (VariableName, VendorGuid, TRUE, &Property, &VarCheckFunction);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_INFO, "[Variable]: Var Check UEFI defined variable fail %r - %g:%s\n", Status, VendorGuid, VariableName));
//
// To prevent name collisions with possible future globally defined variables,
// other internal firmware data variables that are not defined here must be
// saved with a unique VendorGuid other than EFI_GLOBAL_VARIABLE or
// any other GUID defined by the UEFI Specification. Implementations must
// only permit the creation of variables with a UEFI Specification-defined
// VendorGuid when these variables are documented in the UEFI Specification.
//
DEBUG ((EFI_D_INFO, "Variable Check UEFI defined variable fail %r - %s not in %g namespace\n", Status, VariableName, VendorGuid));
return Status;
}
}
@@ -814,27 +826,29 @@ InternalVarCheckSetVariableCheck (
DEBUG ((EFI_D_INFO, "[Variable]: Var Check ReadOnly variable fail %r - %g:%s\n", EFI_WRITE_PROTECTED, VendorGuid, VariableName));
return EFI_WRITE_PROTECTED;
}
if (!((DataSize == 0) || (Attributes == 0))) {
if (!((((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) && (DataSize == 0)) || (Attributes == 0))) {
//
// Not to delete variable.
//
if (Attributes != Property->Attributes) {
DEBUG ((EFI_D_INFO, "[Variable]: Var Check Attributes(0x%08x to 0x%08x) fail %r - %g:%s\n", Property->Attributes, Attributes, EFI_INVALID_PARAMETER, VendorGuid, VariableName));
if ((Attributes != 0) && ((Attributes & (~EFI_VARIABLE_APPEND_WRITE)) != Property->Attributes)) {
DEBUG ((EFI_D_INFO, "Variable Check Attributes(0x%08x to 0x%08x) fail %r - %g:%s\n", Property->Attributes, Attributes, EFI_INVALID_PARAMETER, VendorGuid, VariableName));
return EFI_INVALID_PARAMETER;
}
if ((DataSize < Property->MinSize) || (DataSize > Property->MaxSize)) {
DEBUG ((EFI_D_INFO, "[Variable]: Var Check DataSize fail(0x%x not in 0x%x - 0x%x) %r - %g:%s\n", DataSize, Property->MinSize, Property->MaxSize, EFI_INVALID_PARAMETER, VendorGuid, VariableName));
return EFI_INVALID_PARAMETER;
}
if (VarCheckFunction != NULL) {
Status = VarCheckFunction (
Property,
DataSize,
Data
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_INFO, "[Variable]: Internal Var Check function fail %r - %g:%s\n", Status, VendorGuid, VariableName));
return Status;
if (DataSize != 0) {
if ((DataSize < Property->MinSize) || (DataSize > Property->MaxSize)) {
DEBUG ((EFI_D_INFO, "Variable Check DataSize fail(0x%x not in 0x%x - 0x%x) %r - %g:%s\n", DataSize, Property->MinSize, Property->MaxSize, EFI_INVALID_PARAMETER, VendorGuid, VariableName));
return EFI_INVALID_PARAMETER;
}
if (VarCheckFunction != NULL) {
Status = VarCheckFunction (
Property,
DataSize,
Data
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_INFO, "Internal Variable Check function fail %r - %g:%s\n", Status, VendorGuid, VariableName));
return Status;
}
}
}
}
@@ -849,7 +863,7 @@ InternalVarCheckSetVariableCheck (
Data
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_INFO, "[Variable]: Var Check handler fail %r - %g:%s\n", Status, VendorGuid, VariableName));
DEBUG ((EFI_D_INFO, "Variable Check handler fail %r - %g:%s\n", Status, VendorGuid, VariableName));
return Status;
}
}
@@ -875,8 +889,8 @@ ReallocateHandlerTable (
// Reallocate memory for check handler table.
//
HandlerTable = ReallocateRuntimePool (
mMaxNumberOfHandler * sizeof (VAR_CHECK_SET_VARIABLE_CHECK_HANDLER),
(mMaxNumberOfHandler + VAR_CHECK_HANDLER_TABLE_SIZE) * sizeof (VAR_CHECK_SET_VARIABLE_CHECK_HANDLER),
mMaxNumberOfHandler * sizeof (VAR_CHECK_SET_VARIABLE_CHECK_HANDLER),
(mMaxNumberOfHandler + VAR_CHECK_HANDLER_TABLE_SIZE) * sizeof (VAR_CHECK_SET_VARIABLE_CHECK_HANDLER),
mHandlerTable
);
@@ -927,6 +941,10 @@ VarCheckRegisterSetVariableCheckHandler (
DEBUG ((EFI_D_INFO, "RegisterSetVariableCheckHandler - 0x%x\n", Handler));
Status = EFI_SUCCESS;
AcquireLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
//
// Check whether the handler list is enough to store new handler.
//
@@ -936,7 +954,7 @@ VarCheckRegisterSetVariableCheckHandler (
//
Status = ReallocateHandlerTable();
if (EFI_ERROR (Status)) {
return Status;
goto Done;
}
}
@@ -946,7 +964,10 @@ VarCheckRegisterSetVariableCheckHandler (
mHandlerTable[mNumberOfHandler] = Handler;
mNumberOfHandler++;
return EFI_SUCCESS;
Done:
ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
return Status;
}
/**
@@ -971,6 +992,8 @@ VariablePropertyGetFunction (
CHAR16 *VariableName;
VAR_CHECK_VARIABLE_PROPERTY *Property;
Property = NULL;
for ( Link = GetFirstNode (&mVarCheckVariableList)
; !IsNull (&mVarCheckVariableList, Link)
; Link = GetNextNode (&mVarCheckVariableList, Link)
@@ -982,14 +1005,57 @@ VariablePropertyGetFunction (
}
}
Property = GetVariableDriverVariableProperty (Name, Guid);
if (Property == NULL) {
GetUefiDefinedVariableProperty (Name, Guid, WildcardMatch, &Property, NULL);
}
GetUefiDefinedVariableProperty (Name, Guid, WildcardMatch, &Property, NULL);
return Property;
}
/**
Internal variable property set.
@param[in] Name Pointer to the variable name.
@param[in] Guid Pointer to the vendor GUID.
@param[in] VariableProperty Pointer to the input variable property.
@retval EFI_SUCCESS The property of variable specified by the Name and Guid was set successfully.
@retval EFI_OUT_OF_RESOURCES There is not enough resource for the variable property set request.
**/
EFI_STATUS
EFIAPI
InternalVarCheckVariablePropertySet (
IN CHAR16 *Name,
IN EFI_GUID *Guid,
IN VAR_CHECK_VARIABLE_PROPERTY *VariableProperty
)
{
EFI_STATUS Status;
VAR_CHECK_VARIABLE_ENTRY *Entry;
CHAR16 *VariableName;
VAR_CHECK_VARIABLE_PROPERTY *Property;
Status = EFI_SUCCESS;
Property = VariablePropertyGetFunction (Name, Guid, FALSE);
if (Property != NULL) {
CopyMem (Property, VariableProperty, sizeof (*VariableProperty));
} else {
Entry = AllocateRuntimeZeroPool (sizeof (*Entry) + StrSize (Name));
if (Entry == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Done;
}
VariableName = (CHAR16 *) ((UINTN) Entry + sizeof (*Entry));
StrnCpy (VariableName, Name, StrLen (Name));
CopyGuid (&Entry->Guid, Guid);
CopyMem (&Entry->VariableProperty, VariableProperty, sizeof (*VariableProperty));
InsertTailList (&mVarCheckVariableList, &Entry->Link);
}
Done:
return Status;
}
/**
Variable property set.
@@ -1014,9 +1080,6 @@ VarCheckVariablePropertySet (
)
{
EFI_STATUS Status;
VAR_CHECK_VARIABLE_ENTRY *Entry;
CHAR16 *VariableName;
VAR_CHECK_VARIABLE_PROPERTY *Property;
if (Name == NULL || Name[0] == 0 || Guid == NULL) {
return EFI_INVALID_PARAMETER;
@@ -1034,27 +1097,10 @@ VarCheckVariablePropertySet (
return EFI_ACCESS_DENIED;
}
Status = EFI_SUCCESS;
AcquireLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
Property = VariablePropertyGetFunction (Name, Guid, FALSE);
if (Property != NULL) {
CopyMem (Property, VariableProperty, sizeof (*VariableProperty));
} else {
Entry = AllocateRuntimeZeroPool (sizeof (*Entry) + StrSize (Name));
if (Entry == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Done;
}
VariableName = (CHAR16 *) ((UINTN) Entry + sizeof (*Entry));
StrnCpy (VariableName, Name, StrLen (Name));
CopyGuid (&Entry->Guid, Guid);
CopyMem (&Entry->VariableProperty, VariableProperty, sizeof (*VariableProperty));
InsertTailList (&mVarCheckVariableList, &Entry->Link);
}
Status = InternalVarCheckVariablePropertySet (Name, Guid, VariableProperty);
Done:
ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
return Status;
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,17 +1,16 @@
/** @file
Implement all four UEFI Runtime Variable services for the nonvolatile
and volatile storage space and install variable architecture protocol.
Copyright (C) 2013, Red Hat, Inc.
Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
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
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
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
@@ -34,7 +33,7 @@ EDKII_VAR_CHECK_PROTOCOL mVarCheck = { VarCheckRegisterSe
/**
Return TRUE if ExitBootServices () has been called.
@retval TRUE If ExitBootServices () has been called.
**/
BOOLEAN
@@ -49,8 +48,8 @@ AtRuntime (
/**
Initializes a basic mutual exclusion lock.
This function initializes a basic mutual exclusion lock to the released state
and returns the lock. Each lock provides mutual exclusion access at its task
This function initializes a basic mutual exclusion lock to the released state
and returns the lock. Each lock provides mutual exclusion access at its task
priority level. Since there is no preemption or multiprocessor support in EFI,
acquiring the lock only consists of raising to the locks TPL.
If Lock is NULL, then ASSERT().
@@ -141,7 +140,7 @@ GetFtwProtocol (
&gEfiFaultTolerantWriteProtocolGuid,
NULL,
FtwProtocol
);
);
return Status;
}
@@ -155,7 +154,7 @@ GetFtwProtocol (
@retval EFI_SUCCESS The interface information for the specified protocol was returned.
@retval EFI_UNSUPPORTED The device does not support the FVB protocol.
@retval EFI_INVALID_PARAMETER FvBlockHandle is not a valid EFI_HANDLE or FvBlock is NULL.
**/
EFI_STATUS
GetFvbByHandle (
@@ -176,7 +175,7 @@ GetFvbByHandle (
/**
Function returns an array of handles that support the FVB protocol
in a buffer allocated from pool.
in a buffer allocated from pool.
@param[out] NumberHandles The number of handles returned in Buffer.
@param[out] Buffer A pointer to the buffer to return the requested
@@ -187,7 +186,7 @@ GetFvbByHandle (
@retval EFI_NOT_FOUND No FVB handle was found.
@retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results.
@retval EFI_INVALID_PARAMETER NumberHandles is NULL or Buffer is NULL.
**/
EFI_STATUS
GetFvbCountAndBuffer (
@@ -246,7 +245,7 @@ VariableClassAddressChangeEvent (
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.VolatileVariableBase);
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.HobVariableBase);
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal);
EfiConvertPointer (0x0, (VOID **) &mNvVariableCache);
EfiConvertPointer (0x0, (VOID **) &mNvVariableCache);
EfiConvertPointer (0x0, (VOID **) &mHandlerTable);
for (Index = 0; Index < mNumberOfHandler; Index++) {
EfiConvertPointer (0x0, (VOID **) &mHandlerTable[Index]);
@@ -257,6 +256,12 @@ VariableClassAddressChangeEvent (
Status = EfiConvertList (0x0, &mVarCheckVariableList);
ASSERT_EFI_ERROR (Status);
if (mContextOut.AddressPointer != NULL) {
for (Index = 0; Index < mContextOut.AddressPointerCount; Index++) {
EfiConvertPointer (0x0, (VOID **) &mContextOut.AddressPointer[Index]);
}
}
}
@@ -288,8 +293,14 @@ OnReadyToBoot (
InitializeVariableQuota ();
ReclaimForOS ();
if (FeaturePcdGet (PcdVariableCollectStatistics)) {
gBS->InstallConfigurationTable (&gEfiVariableGuid, gVariableInfo);
if (mVariableModuleGlobal->VariableGlobal.AuthFormat) {
gBS->InstallConfigurationTable (&gEfiAuthenticatedVariableGuid, gVariableInfo);
} else {
gBS->InstallConfigurationTable (&gEfiVariableGuid, gVariableInfo);
}
}
gBS->CloseEvent (Event);
}
/**
@@ -316,17 +327,19 @@ OnEndOfDxe (
if (PcdGetBool (PcdReclaimVariableSpaceAtEndOfDxe)) {
ReclaimForOS ();
}
gBS->CloseEvent (Event);
}
/**
Fault Tolerant Write protocol notification event handler.
Non-Volatile variable write may needs FTW protocol to reclaim when
Non-Volatile variable write may needs FTW protocol to reclaim when
writting variable.
@param[in] Event Event whose notification function is being invoked.
@param[in] Context Pointer to the notification function's context.
**/
VOID
EFIAPI
@@ -394,21 +407,23 @@ FtwNotificationEvent (
DEBUG ((DEBUG_WARN, "Variable driver failed to add EFI_MEMORY_RUNTIME attribute to Flash.\n"));
}
}
Status = VariableWriteServiceInitialize ();
ASSERT_EFI_ERROR (Status);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Variable write service initialization failed. Status = %r\n", Status));
}
//
// Install the Variable Write Architectural protocol.
//
Status = gBS->InstallProtocolInterface (
&mHandle,
&gEfiVariableWriteArchProtocolGuid,
&gEfiVariableWriteArchProtocolGuid,
EFI_NATIVE_INTERFACE,
NULL
);
ASSERT_EFI_ERROR (Status);
//
// Close the notify event to avoid install gEfiVariableWriteArchProtocolGuid again.
//
@@ -419,13 +434,13 @@ FtwNotificationEvent (
/**
Variable Driver main entry point. The Variable driver places the 4 EFI
runtime services in the EFI System Table and installs arch protocols
for variable read and write services being availible. It also registers
runtime services in the EFI System Table and installs arch protocols
for variable read and write services being available. It also registers
a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
@param[in] ImageHandle The firmware allocated handle for the EFI image.
@param[in] ImageHandle The firmware allocated handle for the EFI image.
@param[in] SystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS Variable service successfully initialized.
**/
@@ -463,13 +478,13 @@ VariableServiceInitialize (
SystemTable->RuntimeServices->GetNextVariableName = VariableServiceGetNextVariableName;
SystemTable->RuntimeServices->SetVariable = VariableServiceSetVariable;
SystemTable->RuntimeServices->QueryVariableInfo = VariableServiceQueryVariableInfo;
//
// Now install the Variable Runtime Architectural protocol on a new handle.
//
Status = gBS->InstallProtocolInterface (
&mHandle,
&gEfiVariableArchProtocolGuid,
&gEfiVariableArchProtocolGuid,
EFI_NATIVE_INTERFACE,
NULL
);
@@ -477,7 +492,7 @@ VariableServiceInitialize (
//
// Register FtwNotificationEvent () notify function.
//
//
EfiCreateProtocolNotifyEvent (
&gEfiFaultTolerantWriteProtocolGuid,
TPL_CALLBACK,
@@ -500,9 +515,9 @@ VariableServiceInitialize (
// Register the event handling function to reclaim variable for OS usage.
//
Status = EfiCreateEventReadyToBootEx (
TPL_NOTIFY,
OnReadyToBoot,
NULL,
TPL_NOTIFY,
OnReadyToBoot,
NULL,
&ReadyToBootEvent
);
ASSERT_EFI_ERROR (Status);
@@ -0,0 +1,256 @@
/** @file
Provides variable driver extended services.
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
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
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Variable.h"
/**
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.
@param[in] VariableName Name of the variable to be found.
@param[in] VendorGuid Variable vendor GUID to be found.
@param[out] AuthVariableInfo Pointer to AUTH_VARIABLE_INFO structure for
output of the variable found.
@retval EFI_INVALID_PARAMETER If VariableName is not an empty string,
while VendorGuid is NULL.
@retval EFI_SUCCESS Variable successfully found.
@retval EFI_NOT_FOUND Variable not found
**/
EFI_STATUS
EFIAPI
VariableExLibFindVariable (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
OUT AUTH_VARIABLE_INFO *AuthVariableInfo
)
{
EFI_STATUS Status;
VARIABLE_POINTER_TRACK Variable;
AUTHENTICATED_VARIABLE_HEADER *AuthVariable;
Status = FindVariable (
VariableName,
VendorGuid,
&Variable,
&mVariableModuleGlobal->VariableGlobal,
FALSE
);
if (EFI_ERROR (Status)) {
AuthVariableInfo->Data = NULL;
AuthVariableInfo->DataSize = 0;
AuthVariableInfo->Attributes = 0;
AuthVariableInfo->PubKeyIndex = 0;
AuthVariableInfo->MonotonicCount = 0;
AuthVariableInfo->TimeStamp = NULL;
return Status;
}
AuthVariableInfo->DataSize = DataSizeOfVariable (Variable.CurrPtr);
AuthVariableInfo->Data = GetVariableDataPtr (Variable.CurrPtr);
AuthVariableInfo->Attributes = Variable.CurrPtr->Attributes;
if (mVariableModuleGlobal->VariableGlobal.AuthFormat) {
AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable.CurrPtr;
AuthVariableInfo->PubKeyIndex = AuthVariable->PubKeyIndex;
AuthVariableInfo->MonotonicCount = AuthVariable->MonotonicCount;
AuthVariableInfo->TimeStamp = &AuthVariable->TimeStamp;
}
return EFI_SUCCESS;
}
/**
Finds next variable in storage blocks of volatile and non-volatile storage areas.
This code finds next 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.
@param[in] VariableName Name of the variable to be found.
@param[in] VendorGuid Variable vendor GUID to be found.
@param[out] AuthVariableInfo Pointer to AUTH_VARIABLE_INFO structure for
output of the next variable.
@retval EFI_INVALID_PARAMETER If VariableName is not an empty string,
while VendorGuid is NULL.
@retval EFI_SUCCESS Variable successfully found.
@retval EFI_NOT_FOUND Variable not found
**/
EFI_STATUS
EFIAPI
VariableExLibFindNextVariable (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
OUT AUTH_VARIABLE_INFO *AuthVariableInfo
)
{
EFI_STATUS Status;
VARIABLE_HEADER *VariablePtr;
AUTHENTICATED_VARIABLE_HEADER *AuthVariablePtr;
Status = VariableServiceGetNextVariableInternal (
VariableName,
VendorGuid,
&VariablePtr
);
if (EFI_ERROR (Status)) {
AuthVariableInfo->VariableName = NULL;
AuthVariableInfo->VendorGuid = NULL;
AuthVariableInfo->Data = NULL;
AuthVariableInfo->DataSize = 0;
AuthVariableInfo->Attributes = 0;
AuthVariableInfo->PubKeyIndex = 0;
AuthVariableInfo->MonotonicCount = 0;
AuthVariableInfo->TimeStamp = NULL;
return Status;
}
AuthVariableInfo->VariableName = GetVariableNamePtr (VariablePtr);
AuthVariableInfo->VendorGuid = GetVendorGuidPtr (VariablePtr);
AuthVariableInfo->DataSize = DataSizeOfVariable (VariablePtr);
AuthVariableInfo->Data = GetVariableDataPtr (VariablePtr);
AuthVariableInfo->Attributes = VariablePtr->Attributes;
if (mVariableModuleGlobal->VariableGlobal.AuthFormat) {
AuthVariablePtr = (AUTHENTICATED_VARIABLE_HEADER *) VariablePtr;
AuthVariableInfo->PubKeyIndex = AuthVariablePtr->PubKeyIndex;
AuthVariableInfo->MonotonicCount = AuthVariablePtr->MonotonicCount;
AuthVariableInfo->TimeStamp = &AuthVariablePtr->TimeStamp;
}
return EFI_SUCCESS;
}
/**
Update the variable region with Variable information.
@param[in] AuthVariableInfo Pointer AUTH_VARIABLE_INFO structure for
input of the variable.
@retval EFI_SUCCESS The update operation is success.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@retval EFI_WRITE_PROTECTED Variable is write-protected.
@retval EFI_OUT_OF_RESOURCES There is not enough resource.
**/
EFI_STATUS
EFIAPI
VariableExLibUpdateVariable (
IN AUTH_VARIABLE_INFO *AuthVariableInfo
)
{
VARIABLE_POINTER_TRACK Variable;
FindVariable (AuthVariableInfo->VariableName, AuthVariableInfo->VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
return UpdateVariable (
AuthVariableInfo->VariableName,
AuthVariableInfo->VendorGuid,
AuthVariableInfo->Data,
AuthVariableInfo->DataSize,
AuthVariableInfo->Attributes,
AuthVariableInfo->PubKeyIndex,
AuthVariableInfo->MonotonicCount,
&Variable,
AuthVariableInfo->TimeStamp
);
}
/**
Get scratch buffer.
@param[in, out] ScratchBufferSize Scratch buffer size. If input size is greater than
the maximum supported buffer size, this value contains
the maximum supported buffer size as output.
@param[out] ScratchBuffer Pointer to scratch buffer address.
@retval EFI_SUCCESS Get scratch buffer successfully.
@retval EFI_UNSUPPORTED If input size is greater than the maximum supported buffer size.
**/
EFI_STATUS
EFIAPI
VariableExLibGetScratchBuffer (
IN OUT UINTN *ScratchBufferSize,
OUT VOID **ScratchBuffer
)
{
UINTN MaxBufferSize;
MaxBufferSize = mVariableModuleGlobal->ScratchBufferSize;
if (*ScratchBufferSize > MaxBufferSize) {
*ScratchBufferSize = MaxBufferSize;
return EFI_UNSUPPORTED;
}
*ScratchBuffer = GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.VolatileVariableBase));
return EFI_SUCCESS;
}
/**
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
VariableExLibCheckRemainingSpaceForConsistency (
IN UINT32 Attributes,
...
)
{
VA_LIST Marker;
BOOLEAN Return;
VA_START (Marker, Attributes);
Return = CheckRemainingSpaceForConsistencyInternal (Attributes, Marker);
VA_END (Marker);
return Return;
}
/**
Return TRUE if at OS runtime.
@retval TRUE If at OS runtime.
@retval FALSE If at boot time.
**/
BOOLEAN
EFIAPI
VariableExLibAtRuntime (
VOID
)
{
return AtRuntime ();
}
@@ -1,7 +1,8 @@
## @file
# This module installs variable arch protocol and variable write arch protocol.
# Provides variable service.
#
# It provides four EFI_RUNTIME_SERVICES: SetVariable, GetVariable, GetNextVariableName and QueryVariableInfo.
# This module installs variable arch protocol and variable write arch protocol to provide
# variable services: SetVariable, GetVariable, GetNextVariableName and QueryVariableInfo.
#
# Caution: This module requires additional review when modified.
# This driver will have external input - variable data.
@@ -9,14 +10,12 @@
# buffer overflow or integer overflow.
#
# Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
#
# 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
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
# 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
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
@@ -42,7 +41,9 @@
Variable.c
VariableDxe.c
Variable.h
Measurement.c
VarCheck.c
VariableExLib.c
[Packages]
MdePkg/MdePkg.dec
@@ -62,6 +63,8 @@
PcdLib
HobLib
DevicePathLib
TpmMeasurementLib
AuthVariableLib
[Protocols]
gEfiFirmwareVolumeBlockProtocolGuid ## CONSUMES
@@ -74,23 +77,41 @@
gEdkiiVarCheckProtocolGuid ## PRODUCES
[Guids]
## PRODUCES ## GUID # Signature of Variable store header
## CONSUMES ## GUID # Signature of Variable store header
## SOMETIMES_CONSUMES ## HOB
## SOMETIMES_PRODUCES ## SystemTable
gEfiAuthenticatedVariableGuid
## PRODUCES ## GUID # Signature of Variable store header
## CONSUMES ## GUID # Signature of Variable store header
## SOMETIMES_CONSUMES ## HOB
## SOMETIMES_PRODUCES ## SystemTable
gEfiVariableGuid
## SOMETIMES_CONSUMES ## Variable:L"PlatformLang"
## SOMETIMES_PRODUCES ## Variable:L"PlatformLang"
## SOMETIMES_CONSUMES ## Variable:L"Lang"
## SOMETIMES_PRODUCES ## Variable:L"Lang"
## SOMETIMES_CONSUMES ## Variable:L"HwErrRecSupport"
## SOMETIMES_CONSUMES ## Variable:L"SetupMode"
## SOMETIMES_CONSUMES ## Variable:L"PK"
## SOMETIMES_CONSUMES ## Variable:L"KEK"
## SOMETIMES_CONSUMES ## Variable:L"SecureBoot"
## SOMETIMES_CONSUMES ## Variable:L"SignatureSupport"
## SOMETIMES_CONSUMES ## Variable:L"VendorKeys"
gEfiGlobalVariableGuid
## SOMETIMES_CONSUMES ## Variable:L"DB"
## SOMETIMES_CONSUMES ## Variable:L"DBX"
## SOMETIMES_CONSUMES ## Variable:L"DBT"
gEfiImageSecurityDatabaseGuid
gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Event
gEfiSystemNvDataFvGuid ## CONSUMES ## GUID
gEfiHardwareErrorVariableGuid ## SOMETIMES_CONSUMES ## Variable:L"HwErrRec####"
gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event
## SOMETIMES_CONSUMES ## HOB
gEdkiiFaultTolerantWriteGuid
gEdkiiFaultTolerantWriteGuid ## SOMETIMES_CONSUMES ## HOB
gEdkiiVarErrorFlagGuid ## CONSUMES ## GUID
[Pcd]
@@ -98,6 +119,7 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase ## SOMETIMES_CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize ## CONSUMES
@@ -107,7 +129,7 @@
[FeaturePcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics ## CONSUMES # statistic the information of variable.
gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangDeprecate ## CONSUMES
gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangDeprecate ## CONSUMES # Auto update PlatformLang/Lang
[Depex]
TRUE
@@ -1,7 +1,6 @@
/** @file
The sample implementation for SMM variable protocol. And this driver
implements an SMI handler to communicate with the DXE runtime driver
The sample implementation for SMM variable protocol. And this driver
implements an SMI handler to communicate with the DXE runtime driver
to provide variable services.
Caution: This module requires additional review when modified.
@@ -11,20 +10,21 @@
SmmVariableHandler() will receive untrusted input and do basic validation.
Each sub function VariableServiceGetVariable(), VariableServiceGetNextVariableName(),
VariableServiceSetVariable(), VariableServiceQueryVariableInfo(), ReclaimForOS(),
Each sub function VariableServiceGetVariable(), VariableServiceGetNextVariableName(),
VariableServiceSetVariable(), VariableServiceQueryVariableInfo(), ReclaimForOS(),
SmmVariableGetStatistics() should also do validation based on its own knowledge.
Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
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
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
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Protocol/SmmVariable.h>
#include <Protocol/SmmFirmwareVolumeBlock.h>
#include <Protocol/SmmFaultTolerantWrite.h>
@@ -34,7 +34,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Library/SmmServicesTableLib.h>
#include <Library/SmmMemLib.h>
#include <Guid/VariableFormat.h>
#include <Guid/SmmVariableCommon.h>
#include "Variable.h"
@@ -48,6 +47,23 @@ UINTN mVariableBufferPayloadSize;
extern BOOLEAN mEndOfDxe;
extern BOOLEAN mEnableLocking;
/**
SecureBoot Hook for SetVariable.
@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
)
{
return ;
}
/**
This code sets variable in storage blocks (Volatile or Non-Volatile).
@@ -106,7 +122,7 @@ EDKII_SMM_VAR_CHECK_PROTOCOL mSmmVarCheck = { VarCheckRegisterSetVariableCheckHa
/**
Return TRUE if ExitBootServices () has been called.
@retval TRUE If ExitBootServices () has been called.
**/
BOOLEAN
@@ -120,8 +136,8 @@ AtRuntime (
/**
Initializes a basic mutual exclusion lock.
This function initializes a basic mutual exclusion lock to the released state
and returns the lock. Each lock provides mutual exclusion access at its task
This function initializes a basic mutual exclusion lock to the released state
and returns the lock. Each lock provides mutual exclusion access at its task
priority level. Since there is no preemption or multiprocessor support in EFI,
acquiring the lock only consists of raising to the locks TPL.
If Lock is NULL, then ASSERT().
@@ -204,8 +220,8 @@ GetFtwProtocol (
// Locate Smm Fault Tolerent Write protocol
//
Status = gSmst->SmmLocateProtocol (
&gEfiSmmFaultTolerantWriteProtocolGuid,
NULL,
&gEfiSmmFaultTolerantWriteProtocolGuid,
NULL,
FtwProtocol
);
return Status;
@@ -243,7 +259,7 @@ GetFvbByHandle (
/**
Function returns an array of handles that support the SMM FVB protocol
in a buffer allocated from pool.
in a buffer allocated from pool.
@param[out] NumberHandles The number of handles returned in Buffer.
@param[out] Buffer A pointer to the buffer to return the requested
@@ -314,16 +330,17 @@ GetFvbCountAndBuffer (
InfoEntry and InfoSize are external input. Care must be taken to make sure not security issue at runtime.
@param[in, out] InfoEntry A pointer to the buffer of variable information entry.
On input, point to the variable information returned last time. if
On input, point to the variable information returned last time. if
InfoEntry->VendorGuid is zero, return the first information.
On output, point to the next variable information.
@param[in, out] InfoSize On input, the size of the variable information buffer.
On output, the returned variable information size.
@retval EFI_SUCCESS The variable information is found and returned successfully.
@retval EFI_UNSUPPORTED No variable inoformation exists in variable driver. The
PcdVariableCollectStatistics should be set TRUE to support it.
@retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold the next variable information.
@retval EFI_SUCCESS The variable information is found and returned successfully.
@retval EFI_UNSUPPORTED No variable inoformation exists in variable driver. The
PcdVariableCollectStatistics should be set TRUE to support it.
@retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold the next variable information.
@retval EFI_INVALID_PARAMETER Input parameter is invalid.
**/
EFI_STATUS
@@ -338,8 +355,11 @@ SmmVariableGetStatistics (
CHAR16 *InfoName;
EFI_GUID VendorGuid;
ASSERT (InfoEntry != NULL);
VariableInfo = gVariableInfo;
if (InfoEntry == NULL) {
return EFI_INVALID_PARAMETER;
}
VariableInfo = gVariableInfo;
if (VariableInfo == NULL) {
return EFI_UNSUPPORTED;
}
@@ -381,7 +401,7 @@ SmmVariableGetStatistics (
}
VariableInfo = VariableInfo->Next;
};
if (VariableInfo == NULL) {
*InfoSize = 0;
return EFI_SUCCESS;
@@ -399,7 +419,7 @@ SmmVariableGetStatistics (
CopyMem (InfoEntry, VariableInfo, sizeof (VARIABLE_INFO_ENTRY));
CopyMem (InfoName, VariableInfo->Name, StrSize (VariableInfo->Name));
*InfoSize = StatisticsInfoSize;
return EFI_SUCCESS;
}
@@ -411,8 +431,8 @@ SmmVariableGetStatistics (
Caution: This function may receive untrusted input.
This variable data and communicate buffer are external input, so this function will do basic validation.
Each sub function VariableServiceGetVariable(), VariableServiceGetNextVariableName(),
VariableServiceSetVariable(), VariableServiceQueryVariableInfo(), ReclaimForOS(),
Each sub function VariableServiceGetVariable(), VariableServiceGetNextVariableName(),
VariableServiceSetVariable(), VariableServiceQueryVariableInfo(), ReclaimForOS(),
SmmVariableGetStatistics() should also do validation based on its own knowledge.
@param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
@@ -422,11 +442,11 @@ SmmVariableGetStatistics (
be conveyed from a non-SMM environment into an SMM environment.
@param[in, out] CommBufferSize The size of the CommBuffer.
@retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
@retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
should still be called.
@retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should
@retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should
still be called.
@retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
@retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
be called.
@retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
**/
@@ -444,6 +464,7 @@ SmmVariableHandler (
SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *SmmVariableHeader;
SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *GetNextVariableName;
SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *QueryVariableInfo;
SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE *GetPayloadSize;
VARIABLE_INFO_ENTRY *VariableInfo;
SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *VariableToLock;
SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY *CommVariableProperty;
@@ -496,7 +517,7 @@ SmmVariableHandler (
Status = EFI_ACCESS_DENIED;
goto EXIT;
}
InfoSize = OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)
InfoSize = OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)
+ SmmVariableHeader->DataSize + SmmVariableHeader->NameSize;
//
@@ -525,7 +546,7 @@ SmmVariableHandler (
);
CopyMem (SmmVariableFunctionHeader->Data, mVariableBufferPayload, CommBufferPayloadSize);
break;
case SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME:
if (CommBufferPayloadSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {
DEBUG ((EFI_D_ERROR, "GetNextVariableName: SMM communication buffer size invalid!\n"));
@@ -570,7 +591,7 @@ SmmVariableHandler (
);
CopyMem (SmmVariableFunctionHeader->Data, mVariableBufferPayload, CommBufferPayloadSize);
break;
case SMM_VARIABLE_FUNCTION_SET_VARIABLE:
if (CommBufferPayloadSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {
DEBUG ((EFI_D_ERROR, "SetVariable: SMM communication buffer size invalid!\n"));
@@ -618,7 +639,7 @@ SmmVariableHandler (
(UINT8 *)SmmVariableHeader->Name + SmmVariableHeader->NameSize
);
break;
case SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO:
if (CommBufferPayloadSize < sizeof (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO)) {
DEBUG ((EFI_D_ERROR, "QueryVariableInfo: SMM communication buffer size invalid!\n"));
@@ -634,6 +655,16 @@ SmmVariableHandler (
);
break;
case SMM_VARIABLE_FUNCTION_GET_PAYLOAD_SIZE:
if (CommBufferPayloadSize < sizeof (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE)) {
DEBUG ((EFI_D_ERROR, "GetPayloadSize: SMM communication buffer size invalid!\n"));
return EFI_SUCCESS;
}
GetPayloadSize = (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE *) SmmVariableFunctionHeader->Data;
GetPayloadSize->VariablePayloadSize = mVariableBufferPayloadSize;
Status = EFI_SUCCESS;
break;
case SMM_VARIABLE_FUNCTION_READY_TO_BOOT:
mEndOfDxe = TRUE;
//
@@ -647,7 +678,7 @@ SmmVariableHandler (
ReclaimForOS ();
Status = EFI_SUCCESS;
break;
case SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE:
mAtRuntime = TRUE;
Status = EFI_SUCCESS;
@@ -658,15 +689,15 @@ SmmVariableHandler (
InfoSize = TempCommBufferSize - SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
//
// Do not need to check SmmVariableFunctionHeader->Data in SMRAM here.
// It is covered by previous CommBuffer check
// Do not need to check SmmVariableFunctionHeader->Data in SMRAM here.
// It is covered by previous CommBuffer check
//
if (!SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)CommBufferSize, sizeof(UINTN))) {
DEBUG ((EFI_D_ERROR, "GetStatistics: SMM communication buffer in SMRAM!\n"));
Status = EFI_ACCESS_DENIED;
goto EXIT;
}
}
Status = SmmVariableGetStatistics (VariableInfo, &InfoSize);
*CommBufferSize = InfoSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
@@ -784,16 +815,16 @@ SmmEndOfDxeCallback (
/**
SMM Fault Tolerant Write protocol notification event handler.
Non-Volatile variable write may needs FTW protocol to reclaim when
Non-Volatile variable write may needs FTW protocol to reclaim when
writting variable.
@param Protocol Points to the protocol's unique identifier
@param Interface Points to the interface instance
@param Handle The handle on which the interface was installed
@retval EFI_SUCCESS SmmEventCallback runs successfully
@retval EFI_NOT_FOUND The Fvb protocol for variable is not found.
**/
EFI_STATUS
EFIAPI
@@ -808,7 +839,7 @@ SmmFtwNotificationEvent (
EFI_SMM_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol;
EFI_PHYSICAL_ADDRESS NvStorageVariableBase;
UINTN FtwMaxBlockSize;
if (mVariableModuleGlobal->FvbInstance != NULL) {
return EFI_SUCCESS;
}
@@ -839,10 +870,12 @@ SmmFtwNotificationEvent (
}
mVariableModuleGlobal->FvbInstance = FvbProtocol;
Status = VariableWriteServiceInitialize ();
ASSERT_EFI_ERROR (Status);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Variable write service initialization failed. Status = %r\n", Status));
}
//
// Notify the variable wrapper driver the variable write service is ready
//
@@ -853,20 +886,20 @@ SmmFtwNotificationEvent (
NULL
);
ASSERT_EFI_ERROR (Status);
return EFI_SUCCESS;
}
/**
Variable Driver main entry point. The Variable driver places the 4 EFI
runtime services in the EFI System Table and installs arch protocols
runtime services in the EFI System Table and installs arch protocols
for variable read and write services being available. It also registers
a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
@param[in] ImageHandle The firmware allocated handle for the EFI image.
@param[in] ImageHandle The firmware allocated handle for the EFI image.
@param[in] SystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS Variable service successfully initialized.
**/
@@ -908,8 +941,8 @@ VariableServiceInitialize (
);
ASSERT_EFI_ERROR (Status);
mVariableBufferPayloadSize = MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize)) +
OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name) - sizeof (VARIABLE_HEADER);
mVariableBufferPayloadSize = GetNonVolatileMaxVariableSize () +
OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name) - GetVariableHeaderSize ();
Status = gSmst->SmmAllocatePool (
EfiRuntimeServicesData,
@@ -924,7 +957,7 @@ VariableServiceInitialize (
VariableHandle = NULL;
Status = gSmst->SmiHandlerRegister (SmmVariableHandler, &gEfiSmmVariableProtocolGuid, &VariableHandle);
ASSERT_EFI_ERROR (Status);
//
// Notify the variable wrapper driver the variable service is ready
//
@@ -935,7 +968,7 @@ VariableServiceInitialize (
&gSmmVariable
);
ASSERT_EFI_ERROR (Status);
//
// Register EFI_SMM_END_OF_DXE_PROTOCOL_GUID notify function.
//
@@ -948,7 +981,7 @@ VariableServiceInitialize (
//
// Register FtwNotificationEvent () notify function.
//
//
Status = gSmst->SmmRegisterProtocolNotify (
&gEfiSmmFaultTolerantWriteProtocolGuid,
SmmFtwNotificationEvent,
@@ -957,7 +990,7 @@ VariableServiceInitialize (
ASSERT_EFI_ERROR (Status);
SmmFtwNotificationEvent (NULL, NULL, NULL);
return EFI_SUCCESS;
}
@@ -1,16 +1,22 @@
## @file
# Provides SMM variable service.
#
# This module installs SMM variable protocol into SMM protocol database,
# which can be used by SMM driver, and installs SMM variable protocol
# which can be used by SMM driver, and installs SMM variable protocol
# into BS protocol database, which can be used to notify the SMM Runtime
# Dxe driver that the SMM variable service is ready.
# This module should be used with SMM Runtime DXE module together. The
# SMM Runtime DXE module would install variable arch protocol and variable
# This module should be used with SMM Runtime DXE module together. The
# SMM Runtime DXE module would install variable arch protocol and variable
# write arch protocol based on SMM variable module.
#
# Caution: This module requires additional review when modified.
# This driver will have external input - variable data and communicate buffer in SMM mode.
# This external input must be validated carefully to avoid security issue like
# buffer overflow, integer overflow.
# This external input must be validated carefully to avoid security issues such as
# buffer overflow or integer overflow.
# The whole SMM authentication variable design relies on the integrity of flash part and SMM.
# which is assumed to be protected by platform. All variable code and metadata in flash/SMM Memory
# may not be modified without authorization. If platform fails to protect these resources,
# the authentication service provided in this driver will be broken, and the behavior is undefined.
#
# Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
# This program and the accompanying materials
@@ -20,7 +26,6 @@
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
#
##
[Defines]
@@ -46,6 +51,7 @@
VariableSmm.c
VarCheck.c
Variable.h
VariableExLib.c
[Packages]
MdePkg/MdePkg.dec
@@ -65,6 +71,7 @@
PcdLib
DevicePathLib
SmmMemLib
AuthVariableLib
[Protocols]
gEfiSmmFirmwareVolumeBlockProtocolGuid ## CONSUMES
@@ -81,35 +88,55 @@
## PRODUCES ## GUID # Signature of Variable store header
## CONSUMES ## GUID # Signature of Variable store header
## SOMETIMES_CONSUMES ## HOB
## SOMETIMES_PRODUCES ## SystemTable
gEfiAuthenticatedVariableGuid
## PRODUCES ## GUID # Signature of Variable store header
## CONSUMES ## GUID # Signature of Variable store header
## SOMETIMES_CONSUMES ## HOB
## SOMETIMES_PRODUCES ## SystemTable
gEfiVariableGuid
## SOMETIMES_CONSUMES ## Variable:L"PlatformLang"
## SOMETIMES_PRODUCES ## Variable:L"PlatformLang"
## SOMETIMES_CONSUMES ## Variable:L"Lang"
## SOMETIMES_PRODUCES ## Variable:L"Lang"
## SOMETIMES_CONSUMES ## Variable:L"HwErrRecSupport"
## SOMETIMES_CONSUMES ## Variable:L"SetupMode"
## SOMETIMES_CONSUMES ## Variable:L"PK"
## SOMETIMES_CONSUMES ## Variable:L"KEK"
## SOMETIMES_CONSUMES ## Variable:L"SecureBoot"
## SOMETIMES_CONSUMES ## Variable:L"SignatureSupport"
## SOMETIMES_CONSUMES ## Variable:L"VendorKeys"
gEfiGlobalVariableGuid
gSmmVariableWriteGuid ## PRODUCES ## UNDEFINED # Install protocol
## SOMETIMES_CONSUMES ## Variable:L"DB"
## SOMETIMES_CONSUMES ## Variable:L"DBX"
## SOMETIMES_CONSUMES ## Variable:L"DBT"
gEfiImageSecurityDatabaseGuid
gSmmVariableWriteGuid ## PRODUCES ## GUID # Install protocol
gEfiSystemNvDataFvGuid ## CONSUMES ## GUID
gEfiHardwareErrorVariableGuid ## SOMETIMES_CONSUMES ## Variable:L"HwErrRec####"
## SOMETIMES_CONSUMES ## HOB
gEdkiiFaultTolerantWriteGuid
gEdkiiFaultTolerantWriteGuid ## SOMETIMES_CONSUMES ## HOB
gEdkiiVarErrorFlagGuid ## CONSUMES ## GUID
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase ## SOMETIMES_CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase ## SOMETIMES_CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxUserNvVariableSpaceSize ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdBoottimeReservedNvVariableSpaceSize ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdReclaimVariableSpaceAtEndOfDxe ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdReclaimVariableSpaceAtEndOfDxe ## CONSUMES
[FeaturePcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics ## CONSUMES # statistic the information of variable.
gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangDeprecate ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics ## CONSUMES # statistic the information of variable.
gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangDeprecate ## CONSUMES # Auto update PlatformLang/Lang
[Depex]
TRUE
@@ -1,5 +1,4 @@
/** @file
Implement all four UEFI Runtime Variable services for the nonvolatile
and volatile storage space and install variable architecture protocol
based on SMM variable module.
@@ -15,13 +14,13 @@
InitCommunicateBuffer() is really function to check the variable data size.
Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
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
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
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <PiDxe.h>
@@ -39,15 +38,13 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Library/UefiRuntimeLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/PcdLib.h>
#include <Library/UefiLib.h>
#include <Library/BaseLib.h>
#include <Guid/EventGroup.h>
#include <Guid/VariableFormat.h>
#include <Guid/SmmVariableCommon.h>
EFI_HANDLE mHandle = NULL;
EFI_HANDLE mHandle = NULL;
EFI_SMM_VARIABLE_PROTOCOL *mSmmVariable = NULL;
EFI_EVENT mVirtualAddressChangeEvent = NULL;
EFI_SMM_COMMUNICATION_PROTOCOL *mSmmCommunication = NULL;
@@ -59,6 +56,20 @@ EFI_LOCK mVariableServicesLock;
EDKII_VARIABLE_LOCK_PROTOCOL mVariableLock;
EDKII_VAR_CHECK_PROTOCOL mVarCheck;
/**
SecureBoot Hook for SetVariable.
@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
);
/**
Acquires lock only at boot time. Simply returns at runtime.
@@ -115,7 +126,7 @@ ReleaseLockOnlyAtBootTime (
@param[out] DataPtr Points to the data in the communicate buffer.
@param[in] DataSize The data size to send to SMM.
@param[in] Function The function number to initialize the communicate header.
@retval EFI_INVALID_PARAMETER The data size is too big.
@retval EFI_SUCCESS Find the specified variable.
@@ -127,10 +138,10 @@ InitCommunicateBuffer (
IN UINTN Function
)
{
EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader;
SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;
EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader;
SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;
if (DataSize + SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE > mVariableBufferSize) {
return EFI_INVALID_PARAMETER;
}
@@ -138,7 +149,7 @@ InitCommunicateBuffer (
SmmCommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *) mVariableBuffer;
CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);
SmmCommunicateHeader->MessageLength = DataSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *) SmmCommunicateHeader->Data;
SmmVariableFunctionHeader->Function = Function;
if (DataPtr != NULL) {
@@ -155,8 +166,8 @@ InitCommunicateBuffer (
@param[in] DataSize This size of the function header and the data.
@retval EFI_SUCCESS Success is returned from the functin in SMM.
@retval Others Failure is returned from the function in SMM.
@retval Others Failure is returned from the function in SMM.
**/
EFI_STATUS
SendCommunicateBuffer (
@@ -165,9 +176,9 @@ SendCommunicateBuffer (
{
EFI_STATUS Status;
UINTN CommSize;
EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader;
EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader;
SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;
CommSize = DataSize + SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
Status = mSmmCommunication->Communicate (mSmmCommunication, mVariableBufferPhysical, &CommSize);
ASSERT_EFI_ERROR (Status);
@@ -432,7 +443,7 @@ Done:
@param[in, out] DataSize Size of Data found. If size is less than the
data, this value contains the required size.
@param[out] Data Data pointer.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@retval EFI_SUCCESS Find the specified variable.
@retval EFI_NOT_FOUND Not found.
@@ -594,7 +605,6 @@ RuntimeServiceGetNextVariableName (
//
PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + MAX (OutVariableNameSize, InVariableNameSize);
Status = InitCommunicateBuffer ((VOID **)&SmmGetNextVariableName, PayloadSize, SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME);
if (EFI_ERROR (Status)) {
goto Done;
@@ -633,9 +643,9 @@ RuntimeServiceGetNextVariableName (
if (EFI_ERROR (Status)) {
goto Done;
}
CopyGuid (VendorGuid, &SmmGetNextVariableName->Guid);
CopyMem (VariableName, SmmGetNextVariableName->Name, SmmGetNextVariableName->NameSize);
CopyMem (VariableName, SmmGetNextVariableName->Name, SmmGetNextVariableName->NameSize);
Done:
ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
@@ -673,16 +683,16 @@ RuntimeServiceSetVariable (
)
{
EFI_STATUS Status;
UINTN PayloadSize;
UINTN PayloadSize;
SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *SmmVariableHeader;
UINTN VariableNameSize;
//
// Check input parameters.
//
if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {
return EFI_INVALID_PARAMETER;
}
}
if (DataSize != 0 && Data == NULL) {
return EFI_INVALID_PARAMETER;
@@ -700,7 +710,7 @@ RuntimeServiceSetVariable (
}
AcquireLockOnlyAtBootTime(&mVariableServicesLock);
//
// Init the communicate buffer. The buffer data size is:
// SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
@@ -726,6 +736,15 @@ RuntimeServiceSetVariable (
Done:
ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
if (!EfiAtRuntime ()) {
if (!EFI_ERROR (Status)) {
SecureBootHook (
VariableName,
VendorGuid
);
}
}
return Status;
}
@@ -794,7 +813,7 @@ RuntimeServiceQueryVariableInfo (
//
*MaximumVariableSize = SmmQueryVariableInfo->MaximumVariableSize;
*MaximumVariableStorageSize = SmmQueryVariableInfo->MaximumVariableStorageSize;
*RemainingVariableStorageSize = SmmQueryVariableInfo->RemainingVariableStorageSize;
*RemainingVariableStorageSize = SmmQueryVariableInfo->RemainingVariableStorageSize;
Done:
ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
@@ -822,7 +841,7 @@ OnExitBootServices (
// Init the communicate buffer. The buffer data size is:
// SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.
//
InitCommunicateBuffer (NULL, 0, SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE);
InitCommunicateBuffer (NULL, 0, SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE);
//
// Send data to SMM.
@@ -852,11 +871,13 @@ OnReadyToBoot (
// SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.
//
InitCommunicateBuffer (NULL, 0, SMM_VARIABLE_FUNCTION_READY_TO_BOOT);
//
// Send data to SMM.
//
SendCommunicateBuffer (0);
gBS->CloseEvent (Event);
}
@@ -881,13 +902,86 @@ VariableAddressChangeEvent (
EfiConvertPointer (0x0, (VOID **) &mSmmCommunication);
}
/**
This code gets variable payload size.
@param[out] VariablePayloadSize Output pointer to variable payload size.
@retval EFI_SUCCESS Get successfully.
@retval Others Get unsuccessfully.
**/
EFI_STATUS
EFIAPI
GetVariablePayloadSize (
OUT UINTN *VariablePayloadSize
)
{
EFI_STATUS Status;
SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE *SmmGetPayloadSize;
EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader;
SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;
UINTN CommSize;
UINT8 *CommBuffer;
SmmGetPayloadSize = NULL;
CommBuffer = NULL;
if(VariablePayloadSize == NULL) {
return EFI_INVALID_PARAMETER;
}
AcquireLockOnlyAtBootTime(&mVariableServicesLock);
//
// Init the communicate buffer. The buffer data size is:
// SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE);
//
CommSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE);
CommBuffer = AllocateZeroPool (CommSize);
if (CommBuffer == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Done;
}
SmmCommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *) CommBuffer;
CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);
SmmCommunicateHeader->MessageLength = SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE);
SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *) SmmCommunicateHeader->Data;
SmmVariableFunctionHeader->Function = SMM_VARIABLE_FUNCTION_GET_PAYLOAD_SIZE;
SmmGetPayloadSize = (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE *) SmmVariableFunctionHeader->Data;
//
// Send data to SMM.
//
Status = mSmmCommunication->Communicate (mSmmCommunication, CommBuffer, &CommSize);
ASSERT_EFI_ERROR (Status);
Status = SmmVariableFunctionHeader->ReturnStatus;
if (EFI_ERROR (Status)) {
goto Done;
}
//
// Get data from SMM.
//
*VariablePayloadSize = SmmGetPayloadSize->VariablePayloadSize;
Done:
if (CommBuffer != NULL) {
FreePool (CommBuffer);
}
ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
return Status;
}
/**
Initialize variable service and install Variable Architectural protocol.
@param[in] Event Event whose notification function is being invoked.
@param[in] Context Pointer to the notification function's context.
**/
VOID
EFIAPI
@@ -902,15 +996,15 @@ SmmVariableReady (
if (EFI_ERROR (Status)) {
return;
}
Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &mSmmCommunication);
ASSERT_EFI_ERROR (Status);
//
// Allocate memory for variable communicate buffer.
//
mVariableBufferPayloadSize = MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize)) +
OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name) - sizeof (VARIABLE_HEADER);
Status = GetVariablePayloadSize (&mVariableBufferPayloadSize);
ASSERT_EFI_ERROR (Status);
mVariableBufferSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + mVariableBufferPayloadSize;
mVariableBuffer = AllocateRuntimePool (mVariableBufferSize);
ASSERT (mVariableBuffer != NULL);
@@ -924,13 +1018,13 @@ SmmVariableReady (
gRT->GetNextVariableName = RuntimeServiceGetNextVariableName;
gRT->SetVariable = RuntimeServiceSetVariable;
gRT->QueryVariableInfo = RuntimeServiceQueryVariableInfo;
//
// Install the Variable Architectural Protocol on a new handle.
//
Status = gBS->InstallProtocolInterface (
&mHandle,
&gEfiVariableArchProtocolGuid,
&gEfiVariableArchProtocolGuid,
EFI_NATIVE_INTERFACE,
NULL
);
@@ -955,6 +1049,8 @@ SmmVariableReady (
NULL
);
ASSERT_EFI_ERROR (Status);
gBS->CloseEvent (Event);
}
@@ -963,7 +1059,7 @@ SmmVariableReady (
@param[in] Event Event whose notification function is being invoked.
@param[in] Context Pointer to the notification function's context.
**/
VOID
EFIAPI
@@ -982,26 +1078,28 @@ SmmVariableWriteReady (
if (EFI_ERROR (Status)) {
return;
}
Status = gBS->InstallProtocolInterface (
&mHandle,
&gEfiVariableWriteArchProtocolGuid,
&gEfiVariableWriteArchProtocolGuid,
EFI_NATIVE_INTERFACE,
NULL
);
ASSERT_EFI_ERROR (Status);
ASSERT_EFI_ERROR (Status);
gBS->CloseEvent (Event);
}
/**
Variable Driver main entry point. The Variable driver places the 4 EFI
runtime services in the EFI System Table and installs arch protocols
runtime services in the EFI System Table and installs arch protocols
for variable read and write services being available. It also registers
a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
@param[in] ImageHandle The firmware allocated handle for the EFI image.
@param[in] ImageHandle The firmware allocated handle for the EFI image.
@param[in] SystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS Variable service successfully initialized.
**/
@@ -1024,10 +1122,10 @@ VariableSmmRuntimeInitialize (
// Smm variable service is ready
//
EfiCreateProtocolNotifyEvent (
&gEfiSmmVariableProtocolGuid,
TPL_CALLBACK,
SmmVariableReady,
NULL,
&gEfiSmmVariableProtocolGuid,
TPL_CALLBACK,
SmmVariableReady,
NULL,
&SmmVariableRegistration
);
@@ -1035,10 +1133,10 @@ VariableSmmRuntimeInitialize (
// Smm Non-Volatile variable write service is ready
//
EfiCreateProtocolNotifyEvent (
&gSmmVariableWriteGuid,
TPL_CALLBACK,
SmmVariableWriteReady,
NULL,
&gSmmVariableWriteGuid,
TPL_CALLBACK,
SmmVariableWriteReady,
NULL,
&SmmVariableWriteRegistration
);
@@ -1046,11 +1144,11 @@ VariableSmmRuntimeInitialize (
// Register the event to reclaim variable for OS usage.
//
EfiCreateEventReadyToBootEx (
TPL_NOTIFY,
OnReadyToBoot,
NULL,
TPL_NOTIFY,
OnReadyToBoot,
NULL,
&OnReadyToBootEvent
);
);
//
// Register the event to inform SMM variable that it is at runtime.
@@ -1062,7 +1160,7 @@ VariableSmmRuntimeInitialize (
NULL,
&gEfiEventExitBootServicesGuid,
&ExitBootServiceEvent
);
);
//
// Register the event to inform SMM variable that it is at runtime for legacy boot.
@@ -1086,7 +1184,7 @@ VariableSmmRuntimeInitialize (
&gEfiEventVirtualAddressChangeGuid,
&mVirtualAddressChangeEvent
);
return EFI_SUCCESS;
}
@@ -1,24 +1,25 @@
## @file
# This module is the Runtime DXE part correspond to SMM variable module.
# Runtime DXE part corresponding to SMM authenticated variable module.
#
# It installs variable arch protocol and variable write arch protocol to provide
# four EFI_RUNTIME_SERVICES: SetVariable, GetVariable, GetNextVariableName and QueryVariableInfo
# and works with SMM variable module together.
# This module installs variable arch protocol and variable write arch protocol to provide
# variable service. This module need work together with SMM authenticated variable module.
#
# Caution: This module requires additional review when modified.
# This driver will have external input - variable data.
# This external input must be validated carefully to avoid security issues such as
# buffer overflow or integer overflow.
# The whole SMM authentication variable design relies on the integrity of flash part and SMM.
# which is assumed to be protected by platform. All variable code and metadata in flash/SMM Memory
# may not be modified without authorization. If platform fails to protect these resources,
# the authentication service provided in this driver will be broken, and the behavior is undefined.
#
# Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
#
# 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
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
# 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
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
@@ -41,6 +42,7 @@
[Sources]
VariableSmmRuntimeDxe.c
Measurement.c
[Packages]
MdePkg/MdePkg.dec
@@ -48,13 +50,13 @@
[LibraryClasses]
MemoryAllocationLib
BaseLib
BaseLib
UefiBootServicesTableLib
DebugLib
UefiRuntimeLib
DxeServicesTableLib
UefiDriverEntryPoint
PcdLib
TpmMeasurementLib
[Protocols]
gEfiVariableWriteArchProtocolGuid ## PRODUCES
@@ -74,10 +76,15 @@
## CONSUMES ## GUID # Protocol notify
gSmmVariableWriteGuid
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize ## CONSUMES
## SOMETIMES_CONSUMES ## Variable:L"PK"
## SOMETIMES_CONSUMES ## Variable:L"KEK"
## SOMETIMES_CONSUMES ## Variable:L"SecureBoot"
gEfiGlobalVariableGuid
## SOMETIMES_CONSUMES ## Variable:L"DB"
## SOMETIMES_CONSUMES ## Variable:L"DBX"
gEfiImageSecurityDatabaseGuid
[Depex]
gEfiSmmCommunicationProtocolGuid