\r
InitCommunicateBuffer() is really function to check the variable data size.\r
\r
-Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>\r
This program and the accompanying materials \r
are licensed and made available under the terms and conditions of the BSD License \r
which accompanies this distribution. The full text of the license may be found at \r
#include <Protocol/Variable.h>\r
#include <Protocol/SmmCommunication.h>\r
#include <Protocol/SmmVariable.h>\r
+#include <Protocol/VariableLock.h>\r
\r
#include <Library/UefiBootServicesTableLib.h>\r
#include <Library/UefiRuntimeServicesTableLib.h>\r
UINTN mVariableBufferSize;\r
UINTN mVariableBufferPayloadSize;\r
EFI_LOCK mVariableServicesLock;\r
+EDKII_VARIABLE_LOCK_PROTOCOL mVariableLock;\r
+\r
+/**\r
+ SecureBoot Hook for SetVariable.\r
+\r
+ @param[in] VariableName Name of Variable to be found.\r
+ @param[in] VendorGuid Variable vendor GUID.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SecureBootHook (\r
+ IN CHAR16 *VariableName,\r
+ IN EFI_GUID *VendorGuid\r
+ );\r
\r
/**\r
Acquires lock only at boot time. Simply returns at runtime.\r
return SmmVariableFunctionHeader->ReturnStatus;\r
}\r
\r
+/**\r
+ Mark a variable that will become read-only after leaving the DXE phase of execution.\r
+\r
+ @param[in] This The VARIABLE_LOCK_PROTOCOL instance.\r
+ @param[in] VariableName A pointer to the variable name that will be made read-only subsequently.\r
+ @param[in] VendorGuid A pointer to the vendor GUID that will be made read-only subsequently.\r
+\r
+ @retval EFI_SUCCESS The variable specified by the VariableName and the VendorGuid was marked\r
+ as pending to be read-only.\r
+ @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.\r
+ Or VariableName is an empty string.\r
+ @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has\r
+ already been signaled.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough resource to hold the lock request.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VariableLockRequestToLock (\r
+ IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,\r
+ IN CHAR16 *VariableName,\r
+ IN EFI_GUID *VendorGuid\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN VariableNameSize;\r
+ UINTN PayloadSize;\r
+ SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *VariableToLock;\r
+\r
+ if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ VariableNameSize = StrSize (VariableName);\r
+ VariableToLock = NULL;\r
+\r
+ //\r
+ // If VariableName exceeds SMM payload limit. Return failure\r
+ //\r
+ if (VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE, Name)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ AcquireLockOnlyAtBootTime(&mVariableServicesLock);\r
+\r
+ //\r
+ // Init the communicate buffer. The buffer data size is:\r
+ // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.\r
+ //\r
+ PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE, Name) + VariableNameSize;\r
+ Status = InitCommunicateBuffer ((VOID **) &VariableToLock, PayloadSize, SMM_VARIABLE_FUNCTION_LOCK_VARIABLE);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ ASSERT (VariableToLock != NULL);\r
+\r
+ CopyGuid (&VariableToLock->Guid, VendorGuid);\r
+ VariableToLock->NameSize = VariableNameSize;\r
+ CopyMem (VariableToLock->Name, VariableName, VariableToLock->NameSize);\r
+\r
+ //\r
+ // Send data to SMM.\r
+ //\r
+ Status = SendCommunicateBuffer (PayloadSize);\r
+\r
+Done:\r
+ ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
+ return Status;\r
+}\r
\r
/**\r
This code finds variable in storage blocks (Volatile or Non-Volatile).\r
\r
TempDataSize = *DataSize;\r
VariableNameSize = StrSize (VariableName);\r
+ SmmVariableHeader = NULL;\r
\r
//\r
// If VariableName exceeds SMM payload limit. Return failure\r
\r
OutVariableNameSize = *VariableNameSize;\r
InVariableNameSize = StrSize (VariableName);\r
+ SmmGetNextVariableName = NULL;\r
\r
//\r
// If input string exceeds SMM payload limit. Return failure\r
}\r
\r
VariableNameSize = StrSize (VariableName);\r
+ SmmVariableHeader = NULL;\r
\r
//\r
// If VariableName or DataSize exceeds SMM payload limit. Return failure\r
\r
Done:\r
ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
+\r
+ if (!EfiAtRuntime ()) {\r
+ if (!EFI_ERROR (Status)) {\r
+ SecureBootHook (\r
+ VariableName,\r
+ VendorGuid\r
+ );\r
+ }\r
+ }\r
return Status;\r
}\r
\r
UINTN PayloadSize;\r
SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *SmmQueryVariableInfo;\r
\r
+ SmmQueryVariableInfo = NULL;\r
+\r
if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL || Attributes == 0) {\r
return EFI_INVALID_PARAMETER;\r
}\r
IN EFI_SYSTEM_TABLE *SystemTable\r
)\r
{\r
+ EFI_STATUS Status;\r
VOID *SmmVariableRegistration;\r
VOID *SmmVariableWriteRegistration;\r
EFI_EVENT OnReadyToBootEvent;\r
\r
EfiInitializeLock (&mVariableServicesLock, TPL_NOTIFY);\r
\r
+ mVariableLock.RequestToLock = VariableLockRequestToLock;\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &mHandle,\r
+ &gEdkiiVariableLockProtocolGuid,\r
+ &mVariableLock,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
//\r
// Smm variable service is ready\r
//\r