]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkCompatibilityPkg/Compatibility/SmmBaseHelper/SmmBaseHelper.c
BaseTools: Use absolute import in BPDG
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / SmmBaseHelper / SmmBaseHelper.c
index e447dd96ca76b4062376346877beda6e11838bcd..5f220dd476955c7b59425a4cbf79fe3c08cda3d7 100644 (file)
@@ -4,8 +4,15 @@
   This driver is the counterpart of the SMM Base On SMM Base2 Thunk driver. It\r
   provides helping services in SMM to the SMM Base On SMM Base2 Thunk driver.\r
 \r
-  Copyright (c) 2009 - 2010, Intel Corporation\r
-  All rights reserved. This program and the accompanying materials\r
+  Caution: This module requires additional review when modified.\r
+  This driver will have external input - communicate buffer in SMM mode.\r
+  This external input must be validated carefully to avoid security issue like\r
+  buffer overflow, integer overflow.\r
+\r
+  SmmHandlerEntry() will receive untrusted input and do validation.\r
+\r
+  Copyright (c) 2009 - 2015, 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
   http://opensource.org/licenses/bsd-license.php\r
@@ -27,6 +34,7 @@
 #include <Library/MemoryAllocationLib.h>\r
 #include <Library/SynchronizationLib.h>\r
 #include <Library/CpuLib.h>\r
+#include <Library/SmmMemLib.h>\r
 #include <Guid/SmmBaseThunkCommunication.h>\r
 #include <Protocol/SmmBaseHelperReady.h>\r
 #include <Protocol/SmmCpu.h>\r
 #include <Protocol/LoadPe32Image.h>\r
 #include <Protocol/SmmReadyToLock.h>\r
 \r
+/**\r
+  Register SMM image to SMRAM profile.\r
+\r
+  @param[in] FilePath           File path of the image.\r
+  @param[in] ImageBuffer        Image base address.\r
+  @param[in] NumberOfPage       Number of page.\r
+\r
+  @retval TRUE                  Register success.\r
+  @retval FALSE                 Register fail.\r
+\r
+**/\r
+BOOLEAN\r
+RegisterSmramProfileImage (\r
+  IN EFI_DEVICE_PATH_PROTOCOL   *FilePath,\r
+  IN PHYSICAL_ADDRESS           ImageBuffer,\r
+  IN UINTN                      NumberOfPage\r
+  );\r
+\r
+/**\r
+  Unregister SMM image from SMRAM profile.\r
+\r
+  @param[in] FilePath           File path of the image.\r
+  @param[in] ImageBuffer        Image base address.\r
+  @param[in] NumberOfPage       Number of page.\r
+\r
+  @retval TRUE                  Unregister success.\r
+  @retval FALSE                 Unregister fail.\r
+\r
+**/\r
+BOOLEAN\r
+UnregisterSmramProfileImage (\r
+  IN EFI_DEVICE_PATH_PROTOCOL   *FilePath,\r
+  IN PHYSICAL_ADDRESS           ImageBuffer,\r
+  IN UINTN                      NumberOfPage\r
+  );\r
+\r
 ///\r
 /// Structure for tracking paired information of registered Framework SMI handler\r
 /// and correpsonding dispatch handle for SMI handler thunk.\r
@@ -144,17 +188,13 @@ ReadCpuSaveState (
     SaveState = &mFrameworkSmst->CpuSaveState[CpuIndex].Ia32SaveState;\r
   }\r
 \r
-  if (State->x86.SMMRevId < EFI_SMM_MIN_REV_ID_x64) {\r
-    SaveState->SMBASE = State->x86.SMBASE;\r
-    SaveState->SMMRevId = State->x86.SMMRevId;\r
-    SaveState->IORestart = State->x86.IORestart;\r
-    SaveState->AutoHALTRestart = State->x86.AutoHALTRestart;\r
-  } else {\r
-    SaveState->SMBASE = State->x64.SMBASE;\r
-    SaveState->SMMRevId = State->x64.SMMRevId;\r
-    SaveState->IORestart = State->x64.IORestart;\r
-    SaveState->AutoHALTRestart = State->x64.AutoHALTRestart;\r
-  }\r
+  //\r
+  // Note that SMBASE/SMMRevId/IORestart/AutoHALTRestart are in same location in IA32 and X64 CPU Save State Map.\r
+  //\r
+  SaveState->SMBASE = State->x86.SMBASE;\r
+  SaveState->SMMRevId = State->x86.SMMRevId;\r
+  SaveState->IORestart = State->x86.IORestart;\r
+  SaveState->AutoHALTRestart = State->x86.AutoHALTRestart;\r
 \r
   for (Index = 0; Index < sizeof (mCpuSaveStateConvTable) / sizeof (CPU_SAVE_STATE_CONVERSION); Index++) {\r
     ///\r
@@ -188,25 +228,35 @@ WriteCpuSaveState (
   IN EFI_SMM_CPU_SAVE_STATE  *ToWrite\r
   )\r
 {\r
-  EFI_STATUS Status;\r
-  UINTN      Index;\r
+  UINTN                  Index;\r
+  EFI_SMM_CPU_STATE      *State;\r
   EFI_SMI_CPU_SAVE_STATE *SaveState;\r
 \r
+  State = (EFI_SMM_CPU_STATE *)gSmst->CpuSaveState[CpuIndex];\r
+\r
   if (ToWrite != NULL) {\r
     SaveState = &ToWrite->Ia32SaveState;\r
   } else {\r
     SaveState = &mFrameworkSmst->CpuSaveState[CpuIndex].Ia32SaveState;\r
   }\r
+\r
+  //\r
+  // SMMRevId is read-only.\r
+  // Note that SMBASE/IORestart/AutoHALTRestart are in same location in IA32 and X64 CPU Save State Map.\r
+  //\r
+  State->x86.SMBASE = SaveState->SMBASE;\r
+  State->x86.IORestart = SaveState->IORestart;\r
+  State->x86.AutoHALTRestart = SaveState->AutoHALTRestart;\r
   \r
   for (Index = 0; Index < sizeof (mCpuSaveStateConvTable) / sizeof (CPU_SAVE_STATE_CONVERSION); Index++) {\r
-    Status = mSmmCpu->WriteSaveState (\r
-                        mSmmCpu,\r
-                        (UINTN)sizeof (UINT32),\r
-                        mCpuSaveStateConvTable[Index].Register,\r
-                        CpuIndex,\r
-                        ((UINT8 *)SaveState) + \r
-                        mCpuSaveStateConvTable[Index].Offset\r
-                        );\r
+    mSmmCpu->WriteSaveState (\r
+               mSmmCpu,\r
+               (UINTN)sizeof (UINT32),\r
+               mCpuSaveStateConvTable[Index].Register,\r
+               CpuIndex,\r
+               ((UINT8 *)SaveState) +\r
+               mCpuSaveStateConvTable[Index].Offset\r
+               );\r
   }\r
 }\r
 \r
@@ -294,14 +344,12 @@ PageFaultHandler (
   )\r
 {\r
   BOOLEAN        IsHandled;\r
-  UINT64         *PageTable;\r
   UINT64         PFAddress;\r
   UINTN          NumCpuStatePages;\r
   \r
   ASSERT (mPageTableHookEnabled);\r
   AcquireSpinLock (&mPFLock);\r
 \r
-  PageTable = (UINT64*)(UINTN)(AsmReadCr3 () & mPhyMask);\r
   PFAddress = AsmReadCr2 ();\r
   NumCpuStatePages = EFI_SIZE_TO_PAGES (mNumberOfProcessors * sizeof (EFI_SMM_CPU_SAVE_STATE));\r
   IsHandled = FALSE;\r
@@ -672,12 +720,15 @@ LoadImage (
   if (!EFI_ERROR (Status)) {\r
     ///\r
     /// Update MP state in Framework SMST before transferring control to Framework SMM driver entry point\r
-    /// in case it may invoke AP\r
     ///\r
+    mFrameworkSmst->SmmStartupThisAp      = gSmst->SmmStartupThisAp;\r
+    mFrameworkSmst->NumberOfCpus          = mNumberOfProcessors;\r
     mFrameworkSmst->CurrentlyExecutingCpu = gSmst->CurrentlyExecutingCpu;\r
 \r
+    RegisterSmramProfileImage (FilePath, DstBuffer, PageCount);\r
     Status = gBS->StartImage (*ImageHandle, NULL, NULL);\r
     if (EFI_ERROR (Status)) {\r
+      UnregisterSmramProfileImage (FilePath, DstBuffer, PageCount);\r
       mLoadPe32Image->UnLoadPeImage (mLoadPe32Image, *ImageHandle);\r
       *ImageHandle = NULL;\r
       FreePages ((VOID *)(UINTN)DstBuffer, PageCount);\r
@@ -687,7 +738,6 @@ LoadImage (
   return Status;\r
 }\r
 \r
-\r
 /** \r
   Thunk service of EFI_SMM_BASE_PROTOCOL.Register().\r
 \r
@@ -990,6 +1040,10 @@ HelperCommunicate (
 \r
   This SMI handler provides services for the SMM Base Thunk driver.\r
 \r
+  Caution: This function may receive untrusted input during runtime.\r
+  The communicate buffer is external input, so this function will do operations only if the communicate\r
+  buffer is outside of SMRAM so that returning the status code in the buffer won't overwrite anywhere in SMRAM.\r
+\r
   @param[in]     DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().\r
   @param[in]     RegisterContext Points to an optional handler context which was specified when the\r
                                  handler was registered.\r
@@ -1017,32 +1071,35 @@ SmmHandlerEntry (
   SMMBASE_FUNCTION_DATA *FunctionData;\r
 \r
   ASSERT (CommBuffer != NULL);\r
-  ASSERT (*CommBufferSize == sizeof (SMMBASE_FUNCTION_DATA));\r
-\r
-  FunctionData = (SMMBASE_FUNCTION_DATA *)CommBuffer;\r
-\r
-  switch (FunctionData->Function) {\r
-    case SmmBaseFunctionRegister:\r
-      Register (FunctionData);\r
-      break;\r
-    case SmmBaseFunctionUnregister:\r
-      UnRegister (FunctionData);\r
-      break;\r
-    case SmmBaseFunctionRegisterCallback:\r
-      RegisterCallback (FunctionData);\r
-      break;\r
-    case SmmBaseFunctionAllocatePool:\r
-      HelperAllocatePool (FunctionData);\r
-      break;\r
-    case SmmBaseFunctionFreePool:\r
-      HelperFreePool (FunctionData);\r
-      break;\r
-    case SmmBaseFunctionCommunicate:\r
-      HelperCommunicate (FunctionData);\r
-      break;\r
-    default:\r
-      ASSERT (FALSE);\r
-      FunctionData->Status = EFI_UNSUPPORTED;\r
+  ASSERT (CommBufferSize != NULL);\r
+\r
+  if (*CommBufferSize == sizeof (SMMBASE_FUNCTION_DATA) &&\r
+      SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)CommBuffer, (UINT64)*CommBufferSize)) {\r
+    FunctionData = (SMMBASE_FUNCTION_DATA *)CommBuffer;\r
+\r
+    switch (FunctionData->Function) {\r
+      case SmmBaseFunctionRegister:\r
+        Register (FunctionData);\r
+        break;\r
+      case SmmBaseFunctionUnregister:\r
+        UnRegister (FunctionData);\r
+        break;\r
+      case SmmBaseFunctionRegisterCallback:\r
+        RegisterCallback (FunctionData);\r
+        break;\r
+      case SmmBaseFunctionAllocatePool:\r
+        HelperAllocatePool (FunctionData);\r
+        break;\r
+      case SmmBaseFunctionFreePool:\r
+        HelperFreePool (FunctionData);\r
+        break;\r
+      case SmmBaseFunctionCommunicate:\r
+        HelperCommunicate (FunctionData);\r
+        break;\r
+      default:\r
+        DEBUG ((EFI_D_WARN, "SmmBaseHelper: invalid SMM Base function.\n"));\r
+        FunctionData->Status = EFI_UNSUPPORTED;\r
+    }\r
   }\r
   return EFI_SUCCESS;\r
 }\r