]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c
Fix the SMRAM caching range base and size. The original code uses the biggest SMRAM...
[mirror_edk2.git] / MdeModulePkg / Core / PiSmmCore / PiSmmIpl.c
index 65fd328bfe3db262caeed099244ac43fac7cfeb4..608fedfcbe5a5e459a1e3bc4a668d67af8d5ae9d 100644 (file)
@@ -227,6 +227,8 @@ EFI_SMM_CONTROL2_PROTOCOL  *mSmmControl2;
 EFI_SMM_ACCESS2_PROTOCOL   *mSmmAccess;\r
 EFI_SMRAM_DESCRIPTOR       *mCurrentSmramRange;\r
 BOOLEAN                    mSmmLocked = FALSE;\r
+EFI_PHYSICAL_ADDRESS       mSmramCacheBase;\r
+UINT64                     mSmramCacheSize;\r
 \r
 //\r
 // Table of Protocol notification and GUIDed Event notifications that the SMM IPL requires\r
@@ -272,6 +274,49 @@ SMM_IPL_EVENT_NOTIFICATION  mSmmIplEvents[] = {
   { FALSE, FALSE, NULL,                               NULL,                              NULL,                               NULL }\r
 };\r
 \r
+/**\r
+  Find the maximum SMRAM cache range that covers the range specified by SmramRange.\r
+  \r
+  This function searches and joins all adjacent ranges of SmramRange into a range to be cached.\r
+\r
+  @param   SmramRange       The SMRAM range to search from.\r
+  @param   SmramCacheBase   The returned cache range base.\r
+  @param   SmramCacheSize   The returned cache range size.\r
+\r
+**/\r
+VOID\r
+GetSmramCacheRange (\r
+  IN  EFI_SMRAM_DESCRIPTOR *SmramRange,\r
+  OUT EFI_PHYSICAL_ADDRESS *SmramCacheBase,\r
+  OUT UINT64               *SmramCacheSize\r
+  )\r
+{\r
+  UINTN                Index;\r
+  EFI_PHYSICAL_ADDRESS RangeCpuStart;\r
+  UINT64               RangePhysicalSize;\r
+  BOOLEAN              FoundAjacentRange;\r
+\r
+  *SmramCacheBase = SmramRange->CpuStart;\r
+  *SmramCacheSize = SmramRange->PhysicalSize;\r
+\r
+  do {\r
+    FoundAjacentRange = FALSE;\r
+    for (Index = 0; Index < gSmmCorePrivate->SmramRangeCount; Index++) {\r
+      RangeCpuStart     = gSmmCorePrivate->SmramRanges[Index].CpuStart;\r
+      RangePhysicalSize = gSmmCorePrivate->SmramRanges[Index].PhysicalSize;\r
+      if (RangeCpuStart < *SmramCacheBase && *SmramCacheBase == (RangeCpuStart + RangePhysicalSize)) {\r
+        *SmramCacheBase   = RangeCpuStart;\r
+        *SmramCacheSize  += RangePhysicalSize;\r
+        FoundAjacentRange = TRUE;\r
+      } else if ((*SmramCacheBase + *SmramCacheSize) == RangeCpuStart && RangePhysicalSize > 0) {\r
+        *SmramCacheSize  += RangePhysicalSize;\r
+        FoundAjacentRange = TRUE;\r
+      }\r
+    }\r
+  } while (FoundAjacentRange);\r
+  \r
+}\r
+\r
 /**\r
   Indicate whether the driver is currently executing in the SMM Initialization phase.\r
 \r
@@ -515,8 +560,8 @@ SmmIplSmmConfigurationEventNotify (
   // Attempt to reset SMRAM cacheability to UC\r
   //\r
   Status = gDS->SetMemorySpaceAttributes(\r
-                  mCurrentSmramRange->CpuStart\r
-                  mCurrentSmramRange->PhysicalSize,\r
+                  mSmramCacheBase\r
+                  mSmramCacheSize,\r
                   EFI_MEMORY_UC\r
                   );\r
   if (EFI_ERROR (Status)) {\r
@@ -1076,12 +1121,13 @@ SmmIplEntry (
       (VOID *)(UINTN)(mCurrentSmramRange->CpuStart + mCurrentSmramRange->PhysicalSize - 1)\r
       ));\r
 \r
+    GetSmramCacheRange (mCurrentSmramRange, &mSmramCacheBase, &mSmramCacheSize);\r
     //\r
     // Attempt to set SMRAM cacheability to WB\r
     //\r
     Status = gDS->SetMemorySpaceAttributes(\r
-                    mCurrentSmramRange->CpuStart\r
-                    mCurrentSmramRange->PhysicalSize,\r
+                    mSmramCacheBase\r
+                    mSmramCacheSize,\r
                     EFI_MEMORY_WB\r
                     );\r
     if (EFI_ERROR (Status)) {\r
@@ -1129,8 +1175,8 @@ SmmIplEntry (
       // Attempt to reset SMRAM cacheability to UC\r
       //\r
       Status = gDS->SetMemorySpaceAttributes(\r
-                      mCurrentSmramRange->CpuStart\r
-                      mCurrentSmramRange->PhysicalSize,\r
+                      mSmramCacheBase\r
+                      mSmramCacheSize,\r
                       EFI_MEMORY_UC\r
                       );\r
       if (EFI_ERROR (Status)) {\r