]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/PiSmmCore/PiSmmCore.c
Checking if gSmmCorePrivate->CommunicationBuffer is in supported physical address...
[mirror_edk2.git] / MdeModulePkg / Core / PiSmmCore / PiSmmCore.c
index 3222a92a79450ae7faac6f6dcce2d929803ada6f..d8790241e3fd172aa1987443f288bf2846f9ee39 100644 (file)
@@ -85,6 +85,11 @@ SMM_CORE_SMI_HANDLERS  mSmmCoreSmiHandlers[] = {
 UINTN                           mFullSmramRangeCount;\r
 EFI_SMRAM_DESCRIPTOR            *mFullSmramRanges;\r
 \r
+//\r
+// Maximum support address used to check input CommunicationBuffer\r
+//\r
+UINTN  mMaximumSupportAddress = 0;\r
+\r
 /**\r
   Place holder function until all the SMM System Table Service are available.\r
 \r
@@ -274,6 +279,76 @@ SmmEndOfDxeHandler (
   return Status;\r
 }\r
 \r
+/**\r
+  Caculate and save the maximum support address.\r
+\r
+**/\r
+VOID\r
+CaculateMaximumSupportAddress (\r
+  VOID\r
+  )\r
+{\r
+  VOID         *Hob;\r
+  UINT32       RegEax;\r
+  UINT8        PhysicalAddressBits;\r
+\r
+  //\r
+  // Get physical address bits supported.\r
+  //\r
+  Hob = GetFirstHob (EFI_HOB_TYPE_CPU);\r
+  if (Hob != NULL) {\r
+    PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace;\r
+  } else {\r
+    AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
+    if (RegEax >= 0x80000008) {\r
+      AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
+      PhysicalAddressBits = (UINT8) RegEax;\r
+    } else {\r
+      PhysicalAddressBits = 36;\r
+    }\r
+  }\r
+  //\r
+  // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses.\r
+  //\r
+  ASSERT (PhysicalAddressBits <= 52);\r
+  if (PhysicalAddressBits > 48) {\r
+    PhysicalAddressBits = 48;\r
+  }\r
+  \r
+  //\r
+  // Save the maximum support address in one global variable  \r
+  //\r
+  mMaximumSupportAddress = (UINTN) (LShiftU64 (1, PhysicalAddressBits) - 1);\r
+  DEBUG ((EFI_D_INFO, "mMaximumSupportAddress = 0x%lx\n", mMaximumSupportAddress));\r
+}\r
+\r
+/**\r
+  Check if input buffer is in valid address scope or not.\r
+\r
+  @param[in]  Pointer      Pointer to the input buffer.\r
+  @param[in]  BufferSize   Input buffer size in bytes.\r
+\r
+  @retval TRUE    The input buffer is in valid address scope.  \r
+  @retval FALSE   The input buffer is not in valid address scope.  \r
+\r
+**/\r
+BOOLEAN\r
+IsValidPointer (\r
+  IN VOID     *Pointer,\r
+  IN UINTN    BufferSize\r
+  )\r
+{\r
+  if ((UINTN) Pointer > mMaximumSupportAddress) {\r
+    return FALSE;\r
+  }\r
+\r
+  if (BufferSize > (mMaximumSupportAddress - (UINTN) Pointer)) {\r
+    return FALSE;\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
 /**\r
   The main entry point to SMM Foundation.\r
 \r
@@ -323,22 +398,29 @@ SmmEntryPoint (
       //\r
       // Synchronous SMI for SMM Core or request from Communicate protocol\r
       //\r
-      CommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *)gSmmCorePrivate->CommunicationBuffer;\r
-      gSmmCorePrivate->BufferSize -= OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);\r
-      Status = SmiManage (\r
-                 &CommunicateHeader->HeaderGuid, \r
-                 NULL, \r
-                 CommunicateHeader->Data, \r
-                 &gSmmCorePrivate->BufferSize\r
-                 );\r
-\r
-      //\r
-      // Update CommunicationBuffer, BufferSize and ReturnStatus\r
-      // Communicate service finished, reset the pointer to CommBuffer to NULL\r
-      //\r
-      gSmmCorePrivate->BufferSize += OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);\r
-      gSmmCorePrivate->CommunicationBuffer = NULL;\r
-      gSmmCorePrivate->ReturnStatus = (Status == EFI_SUCCESS) ? EFI_SUCCESS : EFI_NOT_FOUND;\r
+      if (!IsValidPointer (gSmmCorePrivate->CommunicationBuffer, gSmmCorePrivate->BufferSize)) {\r
+        //\r
+        // If CommunicationBuffer is not in valid address scope, return EFI_INVALID_PARAMETER\r
+        //\r
+        gSmmCorePrivate->CommunicationBuffer = NULL;\r
+        gSmmCorePrivate->ReturnStatus = EFI_INVALID_PARAMETER;\r
+      } else {\r
+        CommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *)gSmmCorePrivate->CommunicationBuffer;\r
+        gSmmCorePrivate->BufferSize -= OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);\r
+        Status = SmiManage (\r
+                   &CommunicateHeader->HeaderGuid, \r
+                   NULL, \r
+                   CommunicateHeader->Data, \r
+                   &gSmmCorePrivate->BufferSize\r
+                   );\r
+        //\r
+        // Update CommunicationBuffer, BufferSize and ReturnStatus\r
+        // Communicate service finished, reset the pointer to CommBuffer to NULL\r
+        //\r
+        gSmmCorePrivate->BufferSize += OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);\r
+        gSmmCorePrivate->CommunicationBuffer = NULL;\r
+        gSmmCorePrivate->ReturnStatus = (Status == EFI_SUCCESS) ? EFI_SUCCESS : EFI_NOT_FOUND;\r
+      }\r
     }\r
   }\r
 \r
@@ -430,5 +512,10 @@ SmmMain (
 \r
   RegisterSmramProfileHandler ();\r
 \r
+  //\r
+  // Caculate and save maximum support address used in SmmEntryPoint().\r
+  //\r
+  CaculateMaximumSupportAddress ();\r
+\r
   return EFI_SUCCESS;\r
 }\r