summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c
diff options
context:
space:
mode:
Diffstat (limited to 'MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c')
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c214
1 files changed, 156 insertions, 58 deletions
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c
index 30fb5df6c0..0a076ae467 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c
@@ -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;
@@ -60,6 +57,20 @@ 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.
This is a temperary function that will be removed when
@@ -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;
}