]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.c
Add the EDKII_VARIABLE_LOCK_PROTOCOL implementation in SecurityPkg variable drivers.
[mirror_edk2.git] / SecurityPkg / VariableAuthenticated / RuntimeDxe / VariableSmmRuntimeDxe.c
index b7c7f4ffb7bde9356f39a3cce8260eafb5d96cb0..7011343872d9a7c9586b377464d148da46149fb9 100644 (file)
@@ -29,6 +29,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #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
@@ -54,6 +55,7 @@ UINT8                           *mVariableBufferPhysical    = NULL;
 UINTN                            mVariableBufferSize;\r
 UINTN                            mVariableBufferPayloadSize;\r
 EFI_LOCK                         mVariableServicesLock;\r
+EDKII_VARIABLE_LOCK_PROTOCOL     mVariableLock;\r
 \r
 /**\r
   Acquires lock only at boot time. Simply returns at runtime.\r
@@ -173,6 +175,73 @@ SendCommunicateBuffer (
   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
+\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
@@ -740,6 +809,7 @@ VariableSmmRuntimeInitialize (
   IN EFI_SYSTEM_TABLE                       *SystemTable\r
   )\r
 {\r
+  EFI_STATUS                                Status;\r
   VOID                                      *SmmVariableRegistration;\r
   VOID                                      *SmmVariableWriteRegistration;\r
   EFI_EVENT                                 OnReadyToBootEvent;\r
@@ -747,6 +817,15 @@ VariableSmmRuntimeInitialize (
 \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