]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg/VariableRuntimeDxe: factor out boot service accesses
authorArd Biesheuvel <ard.biesheuvel@linaro.org>
Thu, 3 Jan 2019 18:28:24 +0000 (19:28 +0100)
committerArd Biesheuvel <ard.biesheuvel@linaro.org>
Wed, 16 Jan 2019 19:10:51 +0000 (20:10 +0100)
In preparation of providing a standalone MM based variable runtime
driver, move the existing SMM driver to the new MM services table,
and factor out some pieces that are specific to the traditional
driver, mainly related to the use of UEFI boot services, which are
not accessible to standalone MM drivers.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jian J Wang <jian.j.wang@intel.com>
Reviewed-by: Star Zeng <star.zeng@intel.com>
MdeModulePkg/Universal/Variable/RuntimeDxe/PrivilegePolymorphic.h
MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableTraditionalMm.c [new file with mode: 0644]

index 7af22a4ad67157e824aa4c087501eb030a2e5b56..0a886558f4638ebeb6b94d94da005e8ac0cef29b 100644 (file)
@@ -97,4 +97,67 @@ VariableSpeculationBarrier (
   VOID\r
   );\r
 \r
+/**\r
+  Notify the system that the SMM variable driver is ready\r
+**/\r
+VOID\r
+VariableNotifySmmReady (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Notify the system that the SMM variable write driver is ready\r
+**/\r
+VOID\r
+VariableNotifySmmWriteReady (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Variable Driver main entry point. The Variable driver places the 4 EFI\r
+  runtime services in the EFI System Table and installs arch protocols\r
+  for variable read and write services being available. It also registers\r
+  a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.\r
+\r
+  @retval EFI_SUCCESS       Variable service successfully initialized.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MmVariableServiceInitialize (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  This function checks if the buffer is valid per processor architecture and\r
+  does not overlap with SMRAM.\r
+\r
+  @param Buffer The buffer start address to be checked.\r
+  @param Length The buffer length to be checked.\r
+\r
+  @retval TRUE  This buffer is valid per processor architecture and does not\r
+                overlap with SMRAM.\r
+  @retval FALSE This buffer is not valid per processor architecture or overlaps\r
+                with SMRAM.\r
+**/\r
+BOOLEAN\r
+VariableSmmIsBufferOutsideSmmValid (\r
+  IN EFI_PHYSICAL_ADDRESS  Buffer,\r
+  IN UINT64                Length\r
+  );\r
+\r
+/**\r
+  Whether the TCG or TCG2 protocols are installed in the UEFI protocol database.\r
+  This information is used by the MorLock code to infer whether an existing\r
+  MOR variable is legitimate or not.\r
+\r
+  @retval TRUE  Either the TCG or TCG2 protocol is installed in the UEFI\r
+                protocol database\r
+  @retval FALSE Neither the TCG nor the TCG2 protocol is installed in the UEFI\r
+                protocol database\r
+**/\r
+BOOLEAN\r
+VariableHaveTcgProtocols (\r
+  VOID\r
+  );\r
+\r
 #endif\r
index 28aa2893c6f864bfbeffa162422ef2bba3ae1b65..009d96c3a65e6cb2b91d0e18e30b8c70470cbbfd 100644 (file)
@@ -21,7 +21,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/DebugLib.h>\r
 #include <Library/BaseLib.h>\r
 #include <Library/BaseMemoryLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
 #include "Variable.h"\r
 \r
 typedef struct {\r
@@ -419,8 +418,6 @@ MorLockInitAtEndOfDxe (
 {\r
   UINTN      MorSize;\r
   EFI_STATUS MorStatus;\r
-  EFI_STATUS TcgStatus;\r
-  VOID       *TcgInterface;\r
 \r
   if (!mMorLockInitializationRequired) {\r
     //\r
@@ -458,20 +455,7 @@ MorLockInitAtEndOfDxe (
     // can be deduced from the absence of the TCG / TCG2 protocols, as edk2's\r
     // MOR implementation depends on (one of) those protocols.\r
     //\r
-    TcgStatus = gBS->LocateProtocol (\r
-                       &gEfiTcg2ProtocolGuid,\r
-                       NULL,                     // Registration\r
-                       &TcgInterface\r
-                       );\r
-    if (EFI_ERROR (TcgStatus)) {\r
-      TcgStatus = gBS->LocateProtocol (\r
-                         &gEfiTcgProtocolGuid,\r
-                         NULL,                   // Registration\r
-                         &TcgInterface\r
-                         );\r
-    }\r
-\r
-    if (!EFI_ERROR (TcgStatus)) {\r
+    if (VariableHaveTcgProtocols ()) {\r
       //\r
       // The MOR variable originates from the platform firmware; set the MOR\r
       // Control Lock variable to report the locking capability to the OS.\r
index 8c53f84ff6e8e61d85e989716a66cfd70adffaf1..5aa70d74165e0e7980fe78e1379f637c904c8c12 100644 (file)
@@ -15,6 +15,7 @@
   SmmVariableGetStatistics() should also do validation based on its own knowledge.\r
 \r
 Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2018, Linaro, Ltd. 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
@@ -28,18 +29,15 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Protocol/SmmVariable.h>\r
 #include <Protocol/SmmFirmwareVolumeBlock.h>\r
 #include <Protocol/SmmFaultTolerantWrite.h>\r
-#include <Protocol/SmmEndOfDxe.h>\r
+#include <Protocol/MmEndOfDxe.h>\r
 #include <Protocol/SmmVarCheck.h>\r
 \r
-#include <Library/SmmServicesTableLib.h>\r
-#include <Library/SmmMemLib.h>\r
+#include <Library/MmServicesTableLib.h>\r
 \r
 #include <Guid/SmmVariableCommon.h>\r
 #include "Variable.h"\r
 \r
 extern VARIABLE_INFO_ENTRY                           *gVariableInfo;\r
-EFI_HANDLE                                           mSmmVariableHandle      = NULL;\r
-EFI_HANDLE                                           mVariableHandle         = NULL;\r
 BOOLEAN                                              mAtRuntime              = FALSE;\r
 UINT8                                                *mVariableBufferPayload = NULL;\r
 UINTN                                                mVariableBufferPayloadSize;\r
@@ -218,7 +216,7 @@ GetFtwProtocol (
   //\r
   // Locate Smm Fault Tolerent Write protocol\r
   //\r
-  Status = gSmst->SmmLocateProtocol (\r
+  Status = gMmst->MmLocateProtocol (\r
                     &gEfiSmmFaultTolerantWriteProtocolGuid,\r
                     NULL,\r
                     FtwProtocol\r
@@ -248,7 +246,7 @@ GetFvbByHandle (
   //\r
   // To get the SMM FVB protocol interface on the handle\r
   //\r
-  return gSmst->SmmHandleProtocol (\r
+  return gMmst->MmHandleProtocol (\r
                   FvBlockHandle,\r
                   &gEfiSmmFirmwareVolumeBlockProtocolGuid,\r
                   (VOID **) FvBlock\r
@@ -287,7 +285,7 @@ GetFvbCountAndBuffer (
   BufferSize     = 0;\r
   *NumberHandles = 0;\r
   *Buffer        = NULL;\r
-  Status = gSmst->SmmLocateHandle (\r
+  Status = gMmst->MmLocateHandle (\r
                     ByProtocol,\r
                     &gEfiSmmFirmwareVolumeBlockProtocolGuid,\r
                     NULL,\r
@@ -303,7 +301,7 @@ GetFvbCountAndBuffer (
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  Status = gSmst->SmmLocateHandle (\r
+  Status = gMmst->MmLocateHandle (\r
                     ByProtocol,\r
                     &gEfiSmmFirmwareVolumeBlockProtocolGuid,\r
                     NULL,\r
@@ -500,7 +498,7 @@ SmmVariableHandler (
     return EFI_SUCCESS;\r
   }\r
 \r
-  if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {\r
+  if (!VariableSmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {\r
     DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer in SMRAM or overflow!\n"));\r
     return EFI_SUCCESS;\r
   }\r
@@ -911,13 +909,7 @@ SmmFtwNotificationEvent (
   //\r
   // Notify the variable wrapper driver the variable write service is ready\r
   //\r
-  Status = gBS->InstallProtocolInterface (\r
-                  &mSmmVariableHandle,\r
-                  &gSmmVariableWriteGuid,\r
-                  EFI_NATIVE_INTERFACE,\r
-                  NULL\r
-                  );\r
-  ASSERT_EFI_ERROR (Status);\r
+  VariableNotifySmmWriteReady ();\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -929,17 +921,13 @@ SmmFtwNotificationEvent (
   for variable read and write services being available. It also registers\r
   a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.\r
 \r
-  @param[in] ImageHandle    The firmware allocated handle for the EFI image.\r
-  @param[in] SystemTable    A pointer to the EFI System Table.\r
-\r
   @retval EFI_SUCCESS       Variable service successfully initialized.\r
 \r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-VariableServiceInitialize (\r
-  IN EFI_HANDLE                           ImageHandle,\r
-  IN EFI_SYSTEM_TABLE                     *SystemTable\r
+MmVariableServiceInitialize (\r
+  VOID\r
   )\r
 {\r
   EFI_STATUS                              Status;\r
@@ -957,7 +945,7 @@ VariableServiceInitialize (
   // Install the Smm Variable Protocol on a new handle.\r
   //\r
   VariableHandle = NULL;\r
-  Status = gSmst->SmmInstallProtocolInterface (\r
+  Status = gMmst->MmInstallProtocolInterface (\r
                     &VariableHandle,\r
                     &gEfiSmmVariableProtocolGuid,\r
                     EFI_NATIVE_INTERFACE,\r
@@ -965,7 +953,7 @@ VariableServiceInitialize (
                     );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
-  Status = gSmst->SmmInstallProtocolInterface (\r
+  Status = gMmst->MmInstallProtocolInterface (\r
                     &VariableHandle,\r
                     &gEdkiiSmmVarCheckProtocolGuid,\r
                     EFI_NATIVE_INTERFACE,\r
@@ -976,7 +964,7 @@ VariableServiceInitialize (
   mVariableBufferPayloadSize = GetMaxVariableSize () +\r
                                OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name) - GetVariableHeaderSize ();\r
 \r
-  Status = gSmst->SmmAllocatePool (\r
+  Status = gMmst->MmAllocatePool (\r
                     EfiRuntimeServicesData,\r
                     mVariableBufferPayloadSize,\r
                     (VOID **)&mVariableBufferPayload\r
@@ -987,25 +975,19 @@ VariableServiceInitialize (
   /// Register SMM variable SMI handler\r
   ///\r
   VariableHandle = NULL;\r
-  Status = gSmst->SmiHandlerRegister (SmmVariableHandler, &gEfiSmmVariableProtocolGuid, &VariableHandle);\r
+  Status = gMmst->MmiHandlerRegister (SmmVariableHandler, &gEfiSmmVariableProtocolGuid, &VariableHandle);\r
   ASSERT_EFI_ERROR (Status);\r
 \r
   //\r
   // Notify the variable wrapper driver the variable service is ready\r
   //\r
-  Status = SystemTable->BootServices->InstallProtocolInterface (\r
-                                        &mVariableHandle,\r
-                                        &gEfiSmmVariableProtocolGuid,\r
-                                        EFI_NATIVE_INTERFACE,\r
-                                        &gSmmVariable\r
-                                        );\r
-  ASSERT_EFI_ERROR (Status);\r
+  VariableNotifySmmReady ();\r
 \r
   //\r
   // Register EFI_SMM_END_OF_DXE_PROTOCOL_GUID notify function.\r
   //\r
-  Status = gSmst->SmmRegisterProtocolNotify (\r
-                    &gEfiSmmEndOfDxeProtocolGuid,\r
+  Status = gMmst->MmRegisterProtocolNotify (\r
+                    &gEfiMmEndOfDxeProtocolGuid,\r
                     SmmEndOfDxeCallback,\r
                     &SmmEndOfDxeRegistration\r
                     );\r
@@ -1014,7 +996,7 @@ VariableServiceInitialize (
   //\r
   // Register FtwNotificationEvent () notify function.\r
   //\r
-  Status = gSmst->SmmRegisterProtocolNotify (\r
+  Status = gMmst->MmRegisterProtocolNotify (\r
                     &gEfiSmmFaultTolerantWriteProtocolGuid,\r
                     SmmFtwNotificationEvent,\r
                     &SmmFtwRegistration\r
index db7d220e06df7ada8df38a29ec87f023a8b6906c..ed7392cbcffcf40588e46d9074ba26fd0426af50 100644 (file)
@@ -48,6 +48,7 @@
 [Sources]\r
   Reclaim.c\r
   Variable.c\r
+  VariableTraditionalMm.c\r
   VariableSmm.c\r
   VarCheck.c\r
   Variable.h\r
@@ -66,7 +67,7 @@
   BaseLib\r
   SynchronizationLib\r
   UefiLib\r
-  SmmServicesTableLib\r
+  MmServicesTableLib\r
   BaseMemoryLib\r
   DebugLib\r
   DxeServicesTableLib\r
@@ -85,7 +86,7 @@
   ## PRODUCES\r
   ## UNDEFINED # SmiHandlerRegister\r
   gEfiSmmVariableProtocolGuid\r
-  gEfiSmmEndOfDxeProtocolGuid                   ## NOTIFY\r
+  gEfiMmEndOfDxeProtocolGuid                    ## NOTIFY\r
   gEdkiiSmmVarCheckProtocolGuid                 ## PRODUCES\r
   gEfiTcgProtocolGuid                           ## SOMETIMES_CONSUMES\r
   gEfiTcg2ProtocolGuid                          ## SOMETIMES_CONSUMES\r
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableTraditionalMm.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableTraditionalMm.c
new file mode 100644 (file)
index 0000000..84f2d12
--- /dev/null
@@ -0,0 +1,136 @@
+/** @file\r
+\r
+  Parts of the SMM/MM implementation that are specific to traditional MM\r
+\r
+Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved. <BR>\r
+Copyright (c) 2018, Linaro, Ltd. 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
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/SmmMemLib.h>\r
+#include "Variable.h"\r
+\r
+/**\r
+  This function checks if the buffer is valid per processor architecture and\r
+  does not overlap with SMRAM.\r
+\r
+  @param Buffer The buffer start address to be checked.\r
+  @param Length The buffer length to be checked.\r
+\r
+  @retval TRUE  This buffer is valid per processor architecture and does not\r
+                overlap with SMRAM.\r
+  @retval FALSE This buffer is not valid per processor architecture or overlaps\r
+                with SMRAM.\r
+**/\r
+BOOLEAN\r
+VariableSmmIsBufferOutsideSmmValid (\r
+  IN EFI_PHYSICAL_ADDRESS  Buffer,\r
+  IN UINT64                Length\r
+  )\r
+{\r
+  return SmmIsBufferOutsideSmmValid (Buffer, Length);\r
+}\r
+\r
+/**\r
+  Notify the system that the SMM variable driver is ready\r
+**/\r
+VOID\r
+VariableNotifySmmReady (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  EFI_HANDLE            Handle;\r
+\r
+  Handle = NULL;\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &Handle,\r
+                  &gEfiSmmVariableProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  NULL\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+/**\r
+  Notify the system that the SMM variable write driver is ready\r
+**/\r
+VOID\r
+VariableNotifySmmWriteReady (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  EFI_HANDLE            Handle;\r
+\r
+  Handle = NULL;\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &Handle,\r
+                  &gSmmVariableWriteGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  NULL\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+/**\r
+  Variable service MM driver entry point\r
+\r
+  @param[in] ImageHandle    A handle for the image that is initializing this\r
+                            driver\r
+  @param[in] SystemTable    A pointer to the EFI system table\r
+\r
+  @retval EFI_SUCCESS       Variable service successfully initialized.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VariableServiceInitialize (\r
+  IN EFI_HANDLE                           ImageHandle,\r
+  IN EFI_SYSTEM_TABLE                     *SystemTable\r
+  )\r
+{\r
+  return MmVariableServiceInitialize ();\r
+}\r
+\r
+/**\r
+  Whether the TCG or TCG2 protocols are installed in the UEFI protocol database.\r
+  This information is used by the MorLock code to infer whether an existing\r
+  MOR variable is legitimate or not.\r
+\r
+  @retval TRUE  Either the TCG or TCG2 protocol is installed in the UEFI\r
+                protocol database\r
+  @retval FALSE Neither the TCG nor the TCG2 protocol is installed in the UEFI\r
+                protocol database\r
+**/\r
+BOOLEAN\r
+VariableHaveTcgProtocols (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  VOID                  *Interface;\r
+\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiTcg2ProtocolGuid,\r
+                  NULL,                     // Registration\r
+                  &Interface\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+    return TRUE;\r
+  }\r
+\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiTcgProtocolGuid,\r
+                  NULL,                     // Registration\r
+                  &Interface\r
+                  );\r
+  return !EFI_ERROR (Status);\r
+}\r