]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c
UefiCpuPkg/PiSmmCpu: Check for untested memory in GCD
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / SmmCpuMemoryManagement.c
index 2a4a29899862a2d85a48e14576f99db396d8cfee..b2ace6334e760c417e2618ba8dbc861d5298fc7a 100644 (file)
@@ -13,6 +13,13 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include "PiSmmCpuDxeSmm.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
@@ -23,6 +30,9 @@ EFI_MEMORY_DESCRIPTOR *mUefiMemoryMap;
 UINTN                 mUefiMemoryMapSize;\r
 UINTN                 mUefiDescriptorSize;\r
 \r
+EFI_GCD_MEMORY_SPACE_DESCRIPTOR   *mGcdMemSpace       = NULL;\r
+UINTN                             mGcdMemNumberOfDesc = 0;\r
+\r
 PAGE_ATTRIBUTE_TABLE mPageAttributeTable[] = {\r
   {Page4K,  SIZE_4KB, PAGING_4K_ADDRESS_MASK_64},\r
   {Page2M,  SIZE_2MB, PAGING_2M_ADDRESS_MASK_64},\r
@@ -552,12 +562,12 @@ SmmSetMemoryAttributesEx (
                                 BaseAddress and Length cannot be modified.\r
   @retval EFI_INVALID_PARAMETER Length is zero.\r
                                 Attributes specified an illegal combination of attributes that\r
-                                cannot be set together.\r
+                                cannot be cleared together.\r
   @retval EFI_OUT_OF_RESOURCES  There are not enough system resources to modify the attributes of\r
                                 the memory resource range.\r
   @retval EFI_UNSUPPORTED       The processor does not support one or more bytes of the memory\r
                                 resource range specified by BaseAddress and Length.\r
-                                The bit mask of attributes is not support for the memory resource\r
+                                The bit mask of attributes is not supported for the memory resource\r
                                 range specified by BaseAddress and Length.\r
 \r
 **/\r
@@ -604,7 +614,7 @@ SmmClearMemoryAttributesEx (
                                 the memory resource range.\r
   @retval EFI_UNSUPPORTED       The processor does not support one or more bytes of the memory\r
                                 resource range specified by BaseAddress and Length.\r
-                                The bit mask of attributes is not support for the memory resource\r
+                                The bit mask of attributes is not supported for the memory resource\r
                                 range specified by BaseAddress and Length.\r
 \r
 **/\r
@@ -632,12 +642,12 @@ SmmSetMemoryAttributes (
                                 BaseAddress and Length cannot be modified.\r
   @retval EFI_INVALID_PARAMETER Length is zero.\r
                                 Attributes specified an illegal combination of attributes that\r
-                                cannot be set together.\r
+                                cannot be cleared together.\r
   @retval EFI_OUT_OF_RESOURCES  There are not enough system resources to modify the attributes of\r
                                 the memory resource range.\r
   @retval EFI_UNSUPPORTED       The processor does not support one or more bytes of the memory\r
                                 resource range specified by BaseAddress and Length.\r
-                                The bit mask of attributes is not support for the memory resource\r
+                                The bit mask of attributes is not supported for the memory resource\r
                                 range specified by BaseAddress and Length.\r
 \r
 **/\r
@@ -1022,6 +1032,60 @@ MergeMemoryMapForNotPresentEntry (
   return ;\r
 }\r
 \r
+/**\r
+  This function caches the GCD memory map information.\r
+**/\r
+VOID\r
+GetGcdMemoryMap (\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
+  mGcdMemNumberOfDesc = 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
+      mGcdMemNumberOfDesc++;\r
+    }\r
+  }\r
+\r
+  mGcdMemSpace = AllocateZeroPool (mGcdMemNumberOfDesc * sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR));\r
+  ASSERT (mGcdMemSpace != NULL);\r
+  if (mGcdMemSpace == NULL) {\r
+    mGcdMemNumberOfDesc = 0;\r
+    gBS->FreePool (MemSpaceMap);\r
+    return ;\r
+  }\r
+\r
+  mGcdMemNumberOfDesc = 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
+        &mGcdMemSpace[mGcdMemNumberOfDesc],\r
+        &MemSpaceMap[Index],\r
+        sizeof(EFI_GCD_MEMORY_SPACE_DESCRIPTOR)\r
+        );\r
+      mGcdMemNumberOfDesc++;\r
+    }\r
+  }\r
+\r
+  gBS->FreePool (MemSpaceMap);\r
+}\r
+\r
 /**\r
   This function caches the UEFI memory map information.\r
 **/\r
@@ -1081,6 +1145,11 @@ GetUefiMemoryMap (
   ASSERT (mUefiMemoryMap != NULL);\r
 \r
   gBS->FreePool (MemoryMap);\r
+\r
+  //\r
+  // Get additional information from GCD memory map.\r
+  //\r
+  GetGcdMemoryMap ();\r
 }\r
 \r
 /**\r
@@ -1102,33 +1171,52 @@ SetUefiMemMapAttributes (
 \r
   DEBUG ((DEBUG_INFO, "SetUefiMemMapAttributes\n"));\r
 \r
-  if (mUefiMemoryMap == NULL) {\r
-    DEBUG ((DEBUG_INFO, "UefiMemoryMap - NULL\n"));\r
-    return ;\r
+  if (mUefiMemoryMap != NULL) {\r
+    MemoryMapEntryCount = mUefiMemoryMapSize/mUefiDescriptorSize;\r
+    MemoryMap = mUefiMemoryMap;\r
+    for (Index = 0; Index < MemoryMapEntryCount; Index++) {\r
+      if (IsUefiPageNotPresent(MemoryMap)) {\r
+        Status = SmmSetMemoryAttributes (\r
+                   MemoryMap->PhysicalStart,\r
+                   EFI_PAGES_TO_SIZE((UINTN)MemoryMap->NumberOfPages),\r
+                   EFI_MEMORY_RP\r
+                   );\r
+        DEBUG ((\r
+          DEBUG_INFO,\r
+          "UefiMemory protection: 0x%lx - 0x%lx %r\n",\r
+          MemoryMap->PhysicalStart,\r
+          MemoryMap->PhysicalStart + (UINT64)EFI_PAGES_TO_SIZE((UINTN)MemoryMap->NumberOfPages),\r
+          Status\r
+          ));\r
+      }\r
+      MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, mUefiDescriptorSize);\r
+    }\r
   }\r
+  //\r
+  // Do not free mUefiMemoryMap, it will be checked in IsSmmCommBufferForbiddenAddress().\r
+  //\r
 \r
-  MemoryMapEntryCount = mUefiMemoryMapSize/mUefiDescriptorSize;\r
-  MemoryMap = mUefiMemoryMap;\r
-  for (Index = 0; Index < MemoryMapEntryCount; Index++) {\r
-    if (IsUefiPageNotPresent(MemoryMap)) {\r
+  //\r
+  // Set untested memory as not present.\r
+  //\r
+  if (mGcdMemSpace != NULL) {\r
+    for (Index = 0; Index < mGcdMemNumberOfDesc; Index++) {\r
       Status = SmmSetMemoryAttributes (\r
-                 MemoryMap->PhysicalStart,\r
-                 EFI_PAGES_TO_SIZE((UINTN)MemoryMap->NumberOfPages),\r
+                 mGcdMemSpace[Index].BaseAddress,\r
+                 mGcdMemSpace[Index].Length,\r
                  EFI_MEMORY_RP\r
                  );\r
       DEBUG ((\r
         DEBUG_INFO,\r
-        "UefiMemory protection: 0x%lx - 0x%lx %r\n",\r
-        MemoryMap->PhysicalStart,\r
-        MemoryMap->PhysicalStart + (UINT64)EFI_PAGES_TO_SIZE((UINTN)MemoryMap->NumberOfPages),\r
+        "GcdMemory protection: 0x%lx - 0x%lx %r\n",\r
+        mGcdMemSpace[Index].BaseAddress,\r
+        mGcdMemSpace[Index].BaseAddress + mGcdMemSpace[Index].Length,\r
         Status\r
         ));\r
     }\r
-    MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, mUefiDescriptorSize);\r
   }\r
-\r
   //\r
-  // Do free mUefiMemoryMap, it will be checked in IsSmmCommBufferForbiddenAddress().\r
+  // Do not free mGcdMemSpace, it will be checked in IsSmmCommBufferForbiddenAddress().\r
   //\r
 }\r
 \r
@@ -1149,21 +1237,29 @@ IsSmmCommBufferForbiddenAddress (
   UINTN                 MemoryMapEntryCount;\r
   UINTN                 Index;\r
 \r
-  if (mUefiMemoryMap == NULL) {\r
-    return FALSE;\r
+  if (mUefiMemoryMap != NULL) {\r
+    MemoryMap = mUefiMemoryMap;\r
+    MemoryMapEntryCount = mUefiMemoryMapSize/mUefiDescriptorSize;\r
+    for (Index = 0; Index < MemoryMapEntryCount; Index++) {\r
+      if (IsUefiPageNotPresent (MemoryMap)) {\r
+        if ((Address >= MemoryMap->PhysicalStart) &&\r
+            (Address < MemoryMap->PhysicalStart + EFI_PAGES_TO_SIZE((UINTN)MemoryMap->NumberOfPages)) ) {\r
+          return TRUE;\r
+        }\r
+      }\r
+      MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, mUefiDescriptorSize);\r
+    }\r
   }\r
 \r
-  MemoryMap = mUefiMemoryMap;\r
-  MemoryMapEntryCount = mUefiMemoryMapSize/mUefiDescriptorSize;\r
-  for (Index = 0; Index < MemoryMapEntryCount; Index++) {\r
-    if (IsUefiPageNotPresent (MemoryMap)) {\r
-      if ((Address >= MemoryMap->PhysicalStart) &&\r
-          (Address < MemoryMap->PhysicalStart + EFI_PAGES_TO_SIZE((UINTN)MemoryMap->NumberOfPages)) ) {\r
+  if (mGcdMemSpace != NULL) {\r
+    for (Index = 0; Index < mGcdMemNumberOfDesc; Index++) {\r
+      if ((Address >= mGcdMemSpace[Index].BaseAddress) &&\r
+          (Address < mGcdMemSpace[Index].BaseAddress + mGcdMemSpace[Index].Length) ) {\r
         return TRUE;\r
       }\r
     }\r
-    MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, mUefiDescriptorSize);\r
   }\r
+\r
   return FALSE;\r
 }\r
 \r
@@ -1185,7 +1281,7 @@ IsSmmCommBufferForbiddenAddress (
   @retval EFI_UNSUPPORTED       The processor does not support one or more\r
                                 bytes of the memory resource range specified\r
                                 by BaseAddress and Length.\r
-                                The bit mask of attributes is not support for\r
+                                The bit mask of attributes is not supported for\r
                                 the memory resource range specified by\r
                                 BaseAddress and Length.\r
 \r
@@ -1210,17 +1306,17 @@ EdkiiSmmSetMemoryAttributes (
   @param  BaseAddress       The physical address that is the start address of\r
                             a memory region.\r
   @param  Length            The size in bytes of the memory region.\r
-  @param  Attributes        The bit mask of attributes to set for the memory\r
+  @param  Attributes        The bit mask of attributes to clear for the memory\r
                             region.\r
 \r
-  @retval EFI_SUCCESS           The attributes were set for the memory region.\r
+  @retval EFI_SUCCESS           The attributes were cleared for the memory region.\r
   @retval EFI_INVALID_PARAMETER Length is zero.\r
                                 Attributes specified an illegal combination of\r
-                                attributes that cannot be set together.\r
+                                attributes that cannot be cleared together.\r
   @retval EFI_UNSUPPORTED       The processor does not support one or more\r
                                 bytes of the memory resource range specified\r
                                 by BaseAddress and Length.\r
-                                The bit mask of attributes is not support for\r
+                                The bit mask of attributes is not supported for\r
                                 the memory resource range specified by\r
                                 BaseAddress and Length.\r
 \r
@@ -1238,7 +1334,7 @@ EdkiiSmmClearMemoryAttributes (
 }\r
 \r
 /**\r
-  This function retrieve the attributes of the memory region specified by\r
+  This function retrieves the attributes of the memory region specified by\r
   BaseAddress and Length. If different attributes are got from different part\r
   of the memory region, EFI_NO_MAPPING will be returned.\r
 \r
@@ -1256,9 +1352,6 @@ EdkiiSmmClearMemoryAttributes (
   @retval EFI_UNSUPPORTED       The processor does not support one or more\r
                                 bytes of the memory resource range specified\r
                                 by BaseAddress and Length.\r
-                                The bit mask of attributes is not support for\r
-                                the memory resource range specified by\r
-                                BaseAddress and Length.\r
 \r
 **/\r
 EFI_STATUS\r