mirror of https://github.com/acidanthera/audk.git
Add the EDKII_VARIABLE_LOCK_PROTOCOL implementation in SecurityPkg variable drivers.
Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Reviewed-by: Star Zeng <star.zeng@intel.com> git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@14378 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
51547bb879
commit
6ab9f44138
|
@ -35,12 +35,28 @@ VARIABLE_MODULE_GLOBAL *mVariableModuleGlobal;
|
|||
///
|
||||
/// Define a memory cache that improves the search performance for a variable.
|
||||
///
|
||||
VARIABLE_STORE_HEADER *mNvVariableCache = NULL;
|
||||
VARIABLE_STORE_HEADER *mNvVariableCache = NULL;
|
||||
|
||||
///
|
||||
/// The memory entry used for variable statistics data.
|
||||
///
|
||||
VARIABLE_INFO_ENTRY *gVariableInfo = NULL;
|
||||
VARIABLE_INFO_ENTRY *gVariableInfo = NULL;
|
||||
|
||||
///
|
||||
/// The list to store the variables which cannot be set after the EFI_END_OF_DXE_EVENT_GROUP_GUID
|
||||
/// or EVT_GROUP_READY_TO_BOOT event.
|
||||
///
|
||||
LIST_ENTRY mLockedVariableList = INITIALIZE_LIST_HEAD_VARIABLE (mLockedVariableList);
|
||||
|
||||
///
|
||||
/// The flag to indicate whether the platform has left the DXE phase of execution.
|
||||
///
|
||||
BOOLEAN mEndOfDxe = FALSE;
|
||||
|
||||
///
|
||||
/// The flag to indicate whether the variable storage locking is enabled.
|
||||
///
|
||||
BOOLEAN mEnableLocking = TRUE;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -2311,6 +2327,58 @@ IsHwErrRecVariable (
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
Mark a variable that will become read-only after leaving the DXE phase of execution.
|
||||
|
||||
@param[in] This The VARIABLE_LOCK_PROTOCOL instance.
|
||||
@param[in] VariableName A pointer to the variable name that will be made read-only subsequently.
|
||||
@param[in] VendorGuid A pointer to the vendor GUID that will be made read-only subsequently.
|
||||
|
||||
@retval EFI_SUCCESS The variable specified by the VariableName and the VendorGuid was marked
|
||||
as pending to be read-only.
|
||||
@retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.
|
||||
Or VariableName is an empty string.
|
||||
@retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has
|
||||
already been signaled.
|
||||
@retval EFI_OUT_OF_RESOURCES There is not enough resource to hold the lock request.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
VariableLockRequestToLock (
|
||||
IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,
|
||||
IN CHAR16 *VariableName,
|
||||
IN EFI_GUID *VendorGuid
|
||||
)
|
||||
{
|
||||
VARIABLE_ENTRY *Entry;
|
||||
|
||||
if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (mEndOfDxe) {
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
Entry = AllocateRuntimePool (sizeof (*Entry) + StrSize (VariableName));
|
||||
if (Entry == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
DEBUG ((EFI_D_INFO, "[Variable] Lock: %g:%s\n", VendorGuid, VariableName));
|
||||
|
||||
AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
|
||||
|
||||
Entry->Name = (CHAR16 *) (Entry + 1);
|
||||
StrCpy (Entry->Name, VariableName);
|
||||
CopyGuid (&Entry->Guid, VendorGuid);
|
||||
InsertTailList (&mLockedVariableList, &Entry->Link);
|
||||
|
||||
ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
This code checks if variable should be treated as read-only variable.
|
||||
|
||||
|
@ -2627,6 +2695,8 @@ VariableServiceSetVariable (
|
|||
VARIABLE_HEADER *NextVariable;
|
||||
EFI_PHYSICAL_ADDRESS Point;
|
||||
UINTN PayloadSize;
|
||||
LIST_ENTRY *Link;
|
||||
VARIABLE_ENTRY *Entry;
|
||||
|
||||
//
|
||||
// Check input parameters.
|
||||
|
@ -2717,16 +2787,6 @@ VariableServiceSetVariable (
|
|||
}
|
||||
}
|
||||
|
||||
if (AtRuntime ()) {
|
||||
//
|
||||
// HwErrRecSupport Global Variable identifies the level of hardware error record persistence
|
||||
// support implemented by the platform. This variable is only modified by firmware and is read-only to the OS.
|
||||
//
|
||||
if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, L"HwErrRecSupport") == 0)) {
|
||||
return EFI_WRITE_PROTECTED;
|
||||
}
|
||||
}
|
||||
|
||||
AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
|
||||
|
||||
//
|
||||
|
@ -2745,13 +2805,31 @@ VariableServiceSetVariable (
|
|||
mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) Point;
|
||||
}
|
||||
|
||||
if (mEndOfDxe && mEnableLocking) {
|
||||
//
|
||||
// Treat the variables listed in the forbidden variable list as read-only after leaving DXE phase.
|
||||
//
|
||||
for ( Link = GetFirstNode (&mLockedVariableList)
|
||||
; !IsNull (&mLockedVariableList, Link)
|
||||
; Link = GetNextNode (&mLockedVariableList, Link)
|
||||
) {
|
||||
Entry = BASE_CR (Link, VARIABLE_ENTRY, Link);
|
||||
if (CompareGuid (&Entry->Guid, VendorGuid) && (StrCmp (Entry->Name, VariableName) == 0)) {
|
||||
Status = EFI_WRITE_PROTECTED;
|
||||
DEBUG ((EFI_D_INFO, "[Variable]: Changing readonly variable after leaving DXE phase - %g:%s\n", VendorGuid, VariableName));
|
||||
goto Done;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Check whether the input variable is already existed.
|
||||
//
|
||||
Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, TRUE);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
if (((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) && AtRuntime ()) {
|
||||
return EFI_WRITE_PROTECTED;
|
||||
Status = EFI_WRITE_PROTECTED;
|
||||
goto Done;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2776,6 +2854,7 @@ VariableServiceSetVariable (
|
|||
Status = ProcessVariable (VariableName, VendorGuid, Data, DataSize, &Variable, Attributes);
|
||||
}
|
||||
|
||||
Done:
|
||||
InterlockedDecrement (&mVariableModuleGlobal->VariableGlobal.ReentrantState);
|
||||
ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||
#include <Protocol/FaultTolerantWrite.h>
|
||||
#include <Protocol/FirmwareVolumeBlock.h>
|
||||
#include <Protocol/Variable.h>
|
||||
#include <Protocol/VariableLock.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/HobLib.h>
|
||||
#include <Library/UefiDriverEntryPoint.h>
|
||||
|
@ -106,6 +107,12 @@ typedef struct {
|
|||
VOID *Data;
|
||||
} VARIABLE_CACHE_ENTRY;
|
||||
|
||||
typedef struct {
|
||||
EFI_GUID Guid;
|
||||
CHAR16 *Name;
|
||||
LIST_ENTRY Link;
|
||||
} VARIABLE_ENTRY;
|
||||
|
||||
/**
|
||||
Flush the HOB variable to flash.
|
||||
|
||||
|
@ -578,6 +585,29 @@ VariableServiceQueryVariableInfo (
|
|||
OUT UINT64 *MaximumVariableSize
|
||||
);
|
||||
|
||||
/**
|
||||
Mark a variable that will become read-only after leaving the DXE phase of execution.
|
||||
|
||||
@param[in] This The VARIABLE_LOCK_PROTOCOL instance.
|
||||
@param[in] VariableName A pointer to the variable name that will be made read-only subsequently.
|
||||
@param[in] VendorGuid A pointer to the vendor GUID that will be made read-only subsequently.
|
||||
|
||||
@retval EFI_SUCCESS The variable specified by the VariableName and the VendorGuid was marked
|
||||
as pending to be read-only.
|
||||
@retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.
|
||||
Or VariableName is an empty string.
|
||||
@retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has
|
||||
already been signaled.
|
||||
@retval EFI_OUT_OF_RESOURCES There is not enough resource to hold the lock request.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
VariableLockRequestToLock (
|
||||
IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,
|
||||
IN CHAR16 *VariableName,
|
||||
IN EFI_GUID *VendorGuid
|
||||
);
|
||||
|
||||
extern VARIABLE_MODULE_GLOBAL *mVariableModuleGlobal;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -16,11 +16,13 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||
#include "Variable.h"
|
||||
#include "AuthService.h"
|
||||
|
||||
extern VARIABLE_STORE_HEADER *mNvVariableCache;
|
||||
extern VARIABLE_INFO_ENTRY *gVariableInfo;
|
||||
EFI_HANDLE mHandle = NULL;
|
||||
EFI_EVENT mVirtualAddressChangeEvent = NULL;
|
||||
EFI_EVENT mFtwRegistration = NULL;
|
||||
extern VARIABLE_STORE_HEADER *mNvVariableCache;
|
||||
extern VARIABLE_INFO_ENTRY *gVariableInfo;
|
||||
EFI_HANDLE mHandle = NULL;
|
||||
EFI_EVENT mVirtualAddressChangeEvent = NULL;
|
||||
EFI_EVENT mFtwRegistration = NULL;
|
||||
extern BOOLEAN mEndOfDxe;
|
||||
EDKII_VARIABLE_LOCK_PROTOCOL mVariableLock = { VariableLockRequestToLock };
|
||||
|
||||
/**
|
||||
Return TRUE if ExitBootServices () has been called.
|
||||
|
@ -257,12 +259,34 @@ OnReadyToBoot (
|
|||
VOID *Context
|
||||
)
|
||||
{
|
||||
//
|
||||
// Set the End Of DXE bit in case the EFI_END_OF_DXE_EVENT_GROUP_GUID event is not signaled.
|
||||
//
|
||||
mEndOfDxe = TRUE;
|
||||
ReclaimForOS ();
|
||||
if (FeaturePcdGet (PcdVariableCollectStatistics)) {
|
||||
gBS->InstallConfigurationTable (&gEfiAuthenticatedVariableGuid, gVariableInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Notification function of EFI_END_OF_DXE_EVENT_GROUP_GUID event group.
|
||||
|
||||
This is a notification function registered on EFI_END_OF_DXE_EVENT_GROUP_GUID event group.
|
||||
|
||||
@param Event Event whose notification function is being invoked.
|
||||
@param Context Pointer to the notification function's context.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
OnEndOfDxe (
|
||||
EFI_EVENT Event,
|
||||
VOID *Context
|
||||
)
|
||||
{
|
||||
mEndOfDxe = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
Fault Tolerant Write protocol notification event handler.
|
||||
|
@ -378,10 +402,19 @@ VariableServiceInitialize (
|
|||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_EVENT ReadyToBootEvent;
|
||||
EFI_EVENT EndOfDxeEvent;
|
||||
|
||||
Status = VariableCommonInitialize ();
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
&mHandle,
|
||||
&gEdkiiVariableLockProtocolGuid,
|
||||
&mVariableLock,
|
||||
NULL
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
SystemTable->RuntimeServices->GetVariable = VariableServiceGetVariable;
|
||||
SystemTable->RuntimeServices->GetNextVariableName = VariableServiceGetNextVariableName;
|
||||
SystemTable->RuntimeServices->SetVariable = VariableServiceSetVariable;
|
||||
|
@ -428,6 +461,20 @@ VariableServiceInitialize (
|
|||
NULL,
|
||||
&ReadyToBootEvent
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// Register the event handling function to set the End Of DXE flag.
|
||||
//
|
||||
Status = gBS->CreateEventEx (
|
||||
EVT_NOTIFY_SIGNAL,
|
||||
TPL_NOTIFY,
|
||||
OnEndOfDxe,
|
||||
NULL,
|
||||
&gEfiEndOfDxeEventGroupGuid,
|
||||
&EndOfDxeEvent
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -67,11 +67,12 @@
|
|||
gEfiVariableWriteArchProtocolGuid ## ALWAYS_PRODUCES
|
||||
gEfiVariableArchProtocolGuid ## ALWAYS_PRODUCES
|
||||
gEfiFaultTolerantWriteProtocolGuid ## SOMETIMES_CONSUMES
|
||||
gEdkiiVariableLockProtocolGuid ## ALWAYS_PRODUCES
|
||||
|
||||
[Guids]
|
||||
gEfiAuthenticatedVariableGuid ## PRODUCES ## Configuration Table Guid
|
||||
gEfiGlobalVariableGuid ## PRODUCES ## Variable Guid
|
||||
gEfiEventVirtualAddressChangeGuid ## PRODUCES ## Event
|
||||
gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Event
|
||||
gEfiCertTypeRsa2048Sha256Guid
|
||||
gEfiImageSecurityDatabaseGuid
|
||||
gEfiCertX509Guid
|
||||
|
@ -82,6 +83,7 @@
|
|||
gEfiSystemNvDataFvGuid ## CONSUMES
|
||||
gEfiCertDbGuid
|
||||
gEfiHardwareErrorVariableGuid ## SOMETIMES_CONSUMES
|
||||
gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event
|
||||
|
||||
[Pcd]
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
|
||||
|
|
|
@ -29,6 +29,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||
#include <Protocol/SmmFirmwareVolumeBlock.h>
|
||||
#include <Protocol/SmmFaultTolerantWrite.h>
|
||||
#include <Protocol/SmmAccess2.h>
|
||||
#include <Protocol/SmmEndOfDxe.h>
|
||||
|
||||
#include <Library/SmmServicesTableLib.h>
|
||||
|
||||
|
@ -46,15 +47,61 @@ BOOLEAN mAtRuntime = F
|
|||
EFI_GUID mZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
|
||||
UINT8 *mVariableBufferPayload = NULL;
|
||||
UINTN mVariableBufferPayloadSize;
|
||||
extern BOOLEAN mEndOfDxe;
|
||||
extern BOOLEAN mEnableLocking;
|
||||
|
||||
/**
|
||||
|
||||
This code sets variable in storage blocks (Volatile or Non-Volatile).
|
||||
|
||||
@param VariableName Name of Variable to be found.
|
||||
@param VendorGuid Variable vendor GUID.
|
||||
@param Attributes Attribute value of the variable found
|
||||
@param DataSize Size of Data found. If size is less than the
|
||||
data, this value contains the required size.
|
||||
@param Data Data pointer.
|
||||
|
||||
@return EFI_INVALID_PARAMETER Invalid parameter.
|
||||
@return EFI_SUCCESS Set successfully.
|
||||
@return EFI_OUT_OF_RESOURCES Resource not enough to set variable.
|
||||
@return EFI_NOT_FOUND Not found.
|
||||
@return EFI_WRITE_PROTECTED Variable is read-only.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmVariableSetVariable (
|
||||
IN CHAR16 *VariableName,
|
||||
IN EFI_GUID *VendorGuid,
|
||||
IN UINT32 Attributes,
|
||||
IN UINTN DataSize,
|
||||
IN VOID *Data
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Disable write protection when the calling SetVariable() through EFI_SMM_VARIABLE_PROTOCOL.
|
||||
//
|
||||
mEnableLocking = FALSE;
|
||||
Status = VariableServiceSetVariable (
|
||||
VariableName,
|
||||
VendorGuid,
|
||||
Attributes,
|
||||
DataSize,
|
||||
Data
|
||||
);
|
||||
mEnableLocking = TRUE;
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_SMM_VARIABLE_PROTOCOL gSmmVariable = {
|
||||
VariableServiceGetVariable,
|
||||
VariableServiceGetNextVariableName,
|
||||
VariableServiceSetVariable,
|
||||
SmmVariableSetVariable,
|
||||
VariableServiceQueryVariableInfo
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Return TRUE if ExitBootServices () has been called.
|
||||
|
||||
|
@ -455,6 +502,7 @@ SmmVariableHandler (
|
|||
SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *GetNextVariableName;
|
||||
SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *QueryVariableInfo;
|
||||
VARIABLE_INFO_ENTRY *VariableInfo;
|
||||
SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *VariableToLock;
|
||||
UINTN InfoSize;
|
||||
UINTN NameBufferSize;
|
||||
UINTN CommBufferPayloadSize;
|
||||
|
@ -641,6 +689,7 @@ SmmVariableHandler (
|
|||
break;
|
||||
|
||||
case SMM_VARIABLE_FUNCTION_READY_TO_BOOT:
|
||||
mEndOfDxe = TRUE;
|
||||
if (AtRuntime()) {
|
||||
Status = EFI_UNSUPPORTED;
|
||||
break;
|
||||
|
@ -673,6 +722,19 @@ SmmVariableHandler (
|
|||
*CommBufferSize = InfoSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
|
||||
break;
|
||||
|
||||
case SMM_VARIABLE_FUNCTION_LOCK_VARIABLE:
|
||||
if (mEndOfDxe) {
|
||||
Status = EFI_ACCESS_DENIED;
|
||||
} else {
|
||||
VariableToLock = (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *) SmmVariableFunctionHeader->Data;
|
||||
Status = VariableLockRequestToLock (
|
||||
NULL,
|
||||
VariableToLock->Name,
|
||||
&VariableToLock->Guid
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
Status = EFI_UNSUPPORTED;
|
||||
}
|
||||
|
@ -683,6 +745,28 @@ EXIT:
|
|||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
SMM END_OF_DXE protocol notification event handler.
|
||||
|
||||
@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 SmmEndOfDxeCallback runs successfully
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmEndOfDxeCallback (
|
||||
IN CONST EFI_GUID *Protocol,
|
||||
IN VOID *Interface,
|
||||
IN EFI_HANDLE Handle
|
||||
)
|
||||
{
|
||||
DEBUG ((EFI_D_INFO, "[Variable]END_OF_DXE is signaled\n"));
|
||||
mEndOfDxe = TRUE;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
SMM Fault Tolerant Write protocol notification event handler.
|
||||
|
@ -779,6 +863,7 @@ VariableServiceInitialize (
|
|||
VOID *SmmFtwRegistration;
|
||||
EFI_SMM_ACCESS2_PROTOCOL *SmmAccess;
|
||||
UINTN Size;
|
||||
VOID *SmmEndOfDxeRegistration;
|
||||
|
||||
//
|
||||
// Variable initialize.
|
||||
|
@ -848,6 +933,16 @@ VariableServiceInitialize (
|
|||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// Register EFI_SMM_END_OF_DXE_PROTOCOL_GUID notify function.
|
||||
//
|
||||
Status = gSmst->SmmRegisterProtocolNotify (
|
||||
&gEfiSmmEndOfDxeProtocolGuid,
|
||||
SmmEndOfDxeCallback,
|
||||
&SmmEndOfDxeRegistration
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// Register FtwNotificationEvent () notify function.
|
||||
//
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
gEfiSmmVariableProtocolGuid ## ALWAYS_PRODUCES
|
||||
gEfiSmmFaultTolerantWriteProtocolGuid ## SOMETIMES_CONSUMES
|
||||
gEfiSmmAccess2ProtocolGuid ## ALWAYS_CONSUMES
|
||||
gEfiSmmEndOfDxeProtocolGuid ## ALWAYS_CONSUMES
|
||||
|
||||
[Guids]
|
||||
gEfiAuthenticatedVariableGuid ## PRODUCES ## Configuration Table Guid
|
||||
|
|
|
@ -29,6 +29,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||
#include <Protocol/Variable.h>
|
||||
#include <Protocol/SmmCommunication.h>
|
||||
#include <Protocol/SmmVariable.h>
|
||||
#include <Protocol/VariableLock.h>
|
||||
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
|
@ -54,6 +55,7 @@ UINT8 *mVariableBufferPhysical = NULL;
|
|||
UINTN mVariableBufferSize;
|
||||
UINTN mVariableBufferPayloadSize;
|
||||
EFI_LOCK mVariableServicesLock;
|
||||
EDKII_VARIABLE_LOCK_PROTOCOL mVariableLock;
|
||||
|
||||
/**
|
||||
Acquires lock only at boot time. Simply returns at runtime.
|
||||
|
@ -173,6 +175,73 @@ SendCommunicateBuffer (
|
|||
return SmmVariableFunctionHeader->ReturnStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
Mark a variable that will become read-only after leaving the DXE phase of execution.
|
||||
|
||||
@param[in] This The VARIABLE_LOCK_PROTOCOL instance.
|
||||
@param[in] VariableName A pointer to the variable name that will be made read-only subsequently.
|
||||
@param[in] VendorGuid A pointer to the vendor GUID that will be made read-only subsequently.
|
||||
|
||||
@retval EFI_SUCCESS The variable specified by the VariableName and the VendorGuid was marked
|
||||
as pending to be read-only.
|
||||
@retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.
|
||||
Or VariableName is an empty string.
|
||||
@retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has
|
||||
already been signaled.
|
||||
@retval EFI_OUT_OF_RESOURCES There is not enough resource to hold the lock request.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
VariableLockRequestToLock (
|
||||
IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,
|
||||
IN CHAR16 *VariableName,
|
||||
IN EFI_GUID *VendorGuid
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN VariableNameSize;
|
||||
UINTN PayloadSize;
|
||||
SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *VariableToLock;
|
||||
|
||||
if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
VariableNameSize = StrSize (VariableName);
|
||||
|
||||
//
|
||||
// If VariableName exceeds SMM payload limit. Return failure
|
||||
//
|
||||
if (VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE, Name)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
AcquireLockOnlyAtBootTime(&mVariableServicesLock);
|
||||
|
||||
//
|
||||
// Init the communicate buffer. The buffer data size is:
|
||||
// SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
|
||||
//
|
||||
PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE, Name) + VariableNameSize;
|
||||
Status = InitCommunicateBuffer ((VOID **) &VariableToLock, PayloadSize, SMM_VARIABLE_FUNCTION_LOCK_VARIABLE);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Done;
|
||||
}
|
||||
ASSERT (VariableToLock != NULL);
|
||||
|
||||
CopyGuid (&VariableToLock->Guid, VendorGuid);
|
||||
VariableToLock->NameSize = VariableNameSize;
|
||||
CopyMem (VariableToLock->Name, VariableName, VariableToLock->NameSize);
|
||||
|
||||
//
|
||||
// Send data to SMM.
|
||||
//
|
||||
Status = SendCommunicateBuffer (PayloadSize);
|
||||
|
||||
Done:
|
||||
ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
This code finds variable in storage blocks (Volatile or Non-Volatile).
|
||||
|
@ -740,6 +809,7 @@ VariableSmmRuntimeInitialize (
|
|||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
VOID *SmmVariableRegistration;
|
||||
VOID *SmmVariableWriteRegistration;
|
||||
EFI_EVENT OnReadyToBootEvent;
|
||||
|
@ -747,6 +817,15 @@ VariableSmmRuntimeInitialize (
|
|||
|
||||
EfiInitializeLock (&mVariableServicesLock, TPL_NOTIFY);
|
||||
|
||||
mVariableLock.RequestToLock = VariableLockRequestToLock;
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
&mHandle,
|
||||
&gEdkiiVariableLockProtocolGuid,
|
||||
&mVariableLock,
|
||||
NULL
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// Smm variable service is ready
|
||||
//
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
gEfiVariableArchProtocolGuid ## ALWAYS_PRODUCES
|
||||
gEfiSmmCommunicationProtocolGuid
|
||||
gEfiSmmVariableProtocolGuid
|
||||
gEdkiiVariableLockProtocolGuid ## ALWAYS_PRODUCES
|
||||
|
||||
[Guids]
|
||||
gEfiEventVirtualAddressChangeGuid ## PRODUCES ## Event
|
||||
|
|
Loading…
Reference in New Issue