MdePkg/SmmMemLib: Check for untested memory in GCD
authorJiewen Yao <jiewen.yao@intel.com>
Thu, 2 Nov 2017 10:21:13 +0000 (18:21 +0800)
committerJiewen Yao <jiewen.yao@intel.com>
Thu, 26 Jul 2018 14:51:21 +0000 (22:51 +0800)
It treats GCD untested memory as invalid SMM
communication buffer.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
Reviewed-by: Star Zeng <star.zeng@intel.com>
MdePkg/Library/SmmMemLib/SmmMemLib.c
MdePkg/Library/SmmMemLib/SmmMemLib.inf

index 8c78a0b..3f79e46 100644 (file)
 #include <Library/DebugLib.h>\r
 #include <Library/MemoryAllocationLib.h>\r
 #include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/DxeServicesTableLib.h>\r
 #include <Library/SmmServicesTableLib.h>\r
 #include <Library/HobLib.h>\r
 #include <Protocol/SmmAccess2.h>\r
 #include <Protocol/SmmReadyToLock.h>\r
 #include <Protocol/SmmEndOfDxe.h>\r
 \r
+//\r
+// attributes for reserved memory before it is promoted to system memory\r
+//\r
+#define EFI_MEMORY_PRESENT      0x0100000000000000ULL\r
+#define EFI_MEMORY_INITIALIZED  0x0200000000000000ULL\r
+#define EFI_MEMORY_TESTED       0x0400000000000000ULL\r
+\r
 #define NEXT_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \\r
   ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) + (Size)))\r
 \r
@@ -46,10 +54,13 @@ UINTN                 mMemoryMapEntryCount;
 EFI_MEMORY_DESCRIPTOR *mMemoryMap;\r
 UINTN                 mDescriptorSize;\r
 \r
+EFI_GCD_MEMORY_SPACE_DESCRIPTOR   *mSmmMemLibGcdMemSpace       = NULL;\r
+UINTN                             mSmmMemLibGcdMemNumberOfDesc = 0;\r
+\r
 VOID                  *mRegistrationEndOfDxe;\r
 VOID                  *mRegistrationReadyToLock;\r
 \r
-BOOLEAN               mSmmReadyToLock = FALSE;\r
+BOOLEAN               mSmmMemLibSmmReadyToLock = FALSE;\r
 \r
 /**\r
   Calculate and save the maximum support address.\r
@@ -154,7 +165,7 @@ SmmIsBufferOutsideSmmValid (
   //\r
   // Check override for Valid Communication Region\r
   //\r
-  if (mSmmReadyToLock) {\r
+  if (mSmmMemLibSmmReadyToLock) {\r
     EFI_MEMORY_DESCRIPTOR          *MemoryMap;\r
     BOOLEAN                        InValidCommunicationRegion;\r
 \r
@@ -171,12 +182,28 @@ SmmIsBufferOutsideSmmValid (
     if (!InValidCommunicationRegion) {\r
       DEBUG ((\r
         EFI_D_ERROR,\r
-        "SmmIsBufferOutsideSmmValid: Not in ValidCommunicationRegion: Buffer (0x%lx) - Length (0x%lx)",\r
+        "SmmIsBufferOutsideSmmValid: Not in ValidCommunicationRegion: Buffer (0x%lx) - Length (0x%lx)\n",\r
         Buffer,\r
         Length\r
         ));\r
       return FALSE;\r
     }\r
+\r
+    //\r
+    // Check untested memory as invalid communication buffer.\r
+    //\r
+    for (Index = 0; Index < mSmmMemLibGcdMemNumberOfDesc; Index++) {\r
+      if (((Buffer >= mSmmMemLibGcdMemSpace[Index].BaseAddress) && (Buffer < mSmmMemLibGcdMemSpace[Index].BaseAddress + mSmmMemLibGcdMemSpace[Index].Length)) ||\r
+          ((mSmmMemLibGcdMemSpace[Index].BaseAddress >= Buffer) && (mSmmMemLibGcdMemSpace[Index].BaseAddress < Buffer + Length))) {\r
+        DEBUG ((\r
+          EFI_D_ERROR,\r
+          "SmmIsBufferOutsideSmmValid: In Untested Memory Region: Buffer (0x%lx) - Length (0x%lx)\n",\r
+          Buffer,\r
+          Length\r
+          ));\r
+        return FALSE;\r
+      }\r
+    }\r
   }\r
   return TRUE;\r
 }\r
@@ -317,6 +344,61 @@ SmmSetMem (
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Get GCD memory map.\r
+  Only record untested memory as invalid communication buffer.\r
+**/\r
+VOID\r
+SmmMemLibInternalGetGcdMemoryMap (\r
+  VOID\r
+  )\r
+{\r
+  UINTN                            NumberOfDescriptors;\r
+  EFI_GCD_MEMORY_SPACE_DESCRIPTOR  *MemSpaceMap;\r
+  EFI_STATUS                       Status;\r
+  UINTN                            Index;\r
+\r
+  Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemSpaceMap);\r
+  if (EFI_ERROR (Status)) {\r
+    return ;\r
+  }\r
+\r
+  mSmmMemLibGcdMemNumberOfDesc = 0;\r
+  for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
+    if (MemSpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeReserved &&\r
+        (MemSpaceMap[Index].Capabilities & (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED)) ==\r
+          (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED)\r
+          ) {\r
+      mSmmMemLibGcdMemNumberOfDesc++;\r
+    }\r
+  }\r
+\r
+  mSmmMemLibGcdMemSpace = AllocateZeroPool (mSmmMemLibGcdMemNumberOfDesc * sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR));\r
+  ASSERT (mSmmMemLibGcdMemSpace != NULL);\r
+  if (mSmmMemLibGcdMemSpace == NULL) {\r
+    mSmmMemLibGcdMemNumberOfDesc = 0;\r
+    gBS->FreePool (MemSpaceMap);\r
+    return ;\r
+  }\r
+\r
+  mSmmMemLibGcdMemNumberOfDesc = 0;\r
+  for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
+    if (MemSpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeReserved &&\r
+        (MemSpaceMap[Index].Capabilities & (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED)) ==\r
+          (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED)\r
+          ) {\r
+      CopyMem (\r
+        &mSmmMemLibGcdMemSpace[mSmmMemLibGcdMemNumberOfDesc],\r
+        &MemSpaceMap[Index],\r
+        sizeof(EFI_GCD_MEMORY_SPACE_DESCRIPTOR)\r
+        );\r
+      mSmmMemLibGcdMemNumberOfDesc++;\r
+    }\r
+  }\r
+\r
+  gBS->FreePool (MemSpaceMap);\r
+}\r
+\r
 /**\r
   Notification for SMM EndOfDxe protocol.\r
 \r
@@ -415,10 +497,14 @@ SmmLibInternalEndOfDxeNotify (
 \r
   gBS->FreePool (MemoryMap);\r
 \r
+  //\r
+  // Get additional information from GCD memory map.\r
+  //\r
+  SmmMemLibInternalGetGcdMemoryMap ();\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Notification for SMM ReadyToLock protocol.\r
 \r
@@ -436,7 +522,7 @@ SmmLibInternalReadyToLockNotify (
   IN EFI_HANDLE      Handle\r
   )\r
 {\r
-  mSmmReadyToLock = TRUE;\r
+  mSmmMemLibSmmReadyToLock = TRUE;\r
   return EFI_SUCCESS;\r
 }\r
 /**\r
index e4edad3..36576a4 100644 (file)
@@ -43,6 +43,7 @@
 [LibraryClasses]\r
   SmmServicesTableLib\r
   UefiBootServicesTableLib\r
+  DxeServicesTableLib\r
   DebugLib\r
   BaseMemoryLib\r
   HobLib\r