]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg/PiSmmCore: MemoryAttributeTable need keep non-PE record.
authorJiewen Yao <jiewen.yao@intel.com>
Wed, 30 Nov 2016 15:17:53 +0000 (23:17 +0800)
committerJiewen Yao <jiewen.yao@intel.com>
Wed, 7 Dec 2016 05:13:51 +0000 (13:13 +0800)
Current memory attribute table implementation will only mark PE code
to be EfiRuntimeServicesCode, and mark rest to be EfiRuntimeServicesData.

However, there might be a case that a SMM code wants to allocate
EfiRuntimeServicesCode explicitly to let page table protect this region
to be read only. It is unsupported.

This patch enhances the current solution so that MemoryAttributeTable
does not touch non PE image record.
Only the PE image region is forced to be EfiRuntimeServicesCode for
code and EfiRuntimeServicesData for data.

Cc: Jeff Fan <jeff.fan@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
Reviewed-by: Jeff Fan <jeff.fan@intel.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
MdeModulePkg/Core/PiSmmCore/MemoryAttributesTable.c

index 3a5a2c8743738f2fa711e88561ae3bdbe3c63b19..a6ab830d1ecced9732c0210edaf4892a067692c4 100644 (file)
@@ -268,15 +268,19 @@ EnforceMemoryMapAttribute (
   MemoryMapEntry = MemoryMap;\r
   MemoryMapEnd   = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) MemoryMap + MemoryMapSize);\r
   while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) {\r
-    switch (MemoryMapEntry->Type) {\r
-    case EfiRuntimeServicesCode:\r
-      MemoryMapEntry->Attribute |= EFI_MEMORY_RO;\r
-      break;\r
-    case EfiRuntimeServicesData:\r
-      MemoryMapEntry->Attribute |= EFI_MEMORY_XP;\r
-      break;\r
+    if (MemoryMapEntry->Attribute != 0) {\r
+      // It is PE image, the attribute is already set.\r
+    } else {\r
+      switch (MemoryMapEntry->Type) {\r
+      case EfiRuntimeServicesCode:\r
+        MemoryMapEntry->Attribute = EFI_MEMORY_RO;\r
+        break;\r
+      case EfiRuntimeServicesData:\r
+      default:\r
+        MemoryMapEntry->Attribute |= EFI_MEMORY_XP;\r
+        break;\r
+      }\r
     }\r
-\r
     MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);\r
   }\r
 \r
@@ -358,6 +362,21 @@ SetNewRecord (
   PhysicalEnd = TempRecord.PhysicalStart + EfiPagesToSize(TempRecord.NumberOfPages);\r
   NewRecordCount = 0;\r
 \r
+  //\r
+  // Always create a new entry for non-PE image record\r
+  //\r
+  if (ImageRecord->ImageBase > TempRecord.PhysicalStart) {\r
+    NewRecord->Type = TempRecord.Type;\r
+    NewRecord->PhysicalStart = TempRecord.PhysicalStart;\r
+    NewRecord->VirtualStart  = 0;\r
+    NewRecord->NumberOfPages = EfiSizeToPages(ImageRecord->ImageBase - TempRecord.PhysicalStart);\r
+    NewRecord->Attribute     = TempRecord.Attribute;\r
+    NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);\r
+    NewRecordCount ++;\r
+    TempRecord.PhysicalStart = ImageRecord->ImageBase;\r
+    TempRecord.NumberOfPages = EfiSizeToPages(PhysicalEnd - TempRecord.PhysicalStart);\r
+  }\r
+\r
   ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;\r
 \r
   ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink;\r
@@ -452,14 +471,10 @@ GetMaxSplitRecordCount (
     if (ImageRecord == NULL) {\r
       break;\r
     }\r
-    SplitRecordCount += (2 * ImageRecord->CodeSegmentCount + 1);\r
+    SplitRecordCount += (2 * ImageRecord->CodeSegmentCount + 2);\r
     PhysicalStart = ImageRecord->ImageBase + ImageRecord->ImageSize;\r
   } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd));\r
 \r
-  if (SplitRecordCount != 0) {\r
-    SplitRecordCount--;\r
-  }\r
-\r
   return SplitRecordCount;\r
 }\r
 \r
@@ -516,28 +531,16 @@ SplitRecord (
       //\r
       // No more image covered by this range, stop\r
       //\r
-      if ((PhysicalEnd > PhysicalStart) && (ImageRecord != NULL)) {\r
+      if (PhysicalEnd > PhysicalStart) {\r
         //\r
-        // If this is still address in this record, need record.\r
+        // Always create a new entry for non-PE image record\r
         //\r
-        NewRecord = PREVIOUS_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);\r
-        if (NewRecord->Type == EfiRuntimeServicesData) {\r
-          //\r
-          // Last record is DATA, just merge it.\r
-          //\r
-          NewRecord->NumberOfPages = EfiSizeToPages(PhysicalEnd - NewRecord->PhysicalStart);\r
-        } else {\r
-          //\r
-          // Last record is CODE, create a new DATA entry.\r
-          //\r
-          NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);\r
-          NewRecord->Type = EfiRuntimeServicesData;\r
-          NewRecord->PhysicalStart = TempRecord.PhysicalStart;\r
-          NewRecord->VirtualStart  = 0;\r
-          NewRecord->NumberOfPages = TempRecord.NumberOfPages;\r
-          NewRecord->Attribute     = TempRecord.Attribute | EFI_MEMORY_XP;\r
-          TotalNewRecordCount ++;\r
-        }\r
+        NewRecord->Type = TempRecord.Type;\r
+        NewRecord->PhysicalStart = TempRecord.PhysicalStart;\r
+        NewRecord->VirtualStart  = 0;\r
+        NewRecord->NumberOfPages = TempRecord.NumberOfPages;\r
+        NewRecord->Attribute     = TempRecord.Attribute;\r
+        TotalNewRecordCount ++;\r
       }\r
       break;\r
     }\r
@@ -580,6 +583,8 @@ SplitRecord (
    ==>\r
    +---------------+\r
    | Record X      |\r
+   +---------------+\r
+   | Record RtCode |\r
    +---------------+ ----\r
    | Record RtData |     |\r
    +---------------+     |\r
@@ -587,12 +592,16 @@ SplitRecord (
    +---------------+     |\r
    | Record RtData |     |\r
    +---------------+ ----\r
+   | Record RtCode |\r
+   +---------------+ ----\r
    | Record RtData |     |\r
    +---------------+     |\r
    | Record RtCode |     |-> PE/COFF2\r
    +---------------+     |\r
    | Record RtData |     |\r
    +---------------+ ----\r
+   | Record RtCode |\r
+   +---------------+\r
    | Record Y      |\r
    +---------------+\r
 \r
@@ -622,7 +631,7 @@ SplitTable (
   UINTN       TotalSplitRecordCount;\r
   UINTN       AdditionalRecordCount;\r
 \r
-  AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 1) * mImagePropertiesPrivateData.ImageRecordCount;\r
+  AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 2) * mImagePropertiesPrivateData.ImageRecordCount;\r
 \r
   TotalSplitRecordCount = 0;\r
   //\r
@@ -648,11 +657,13 @@ SplitTable (
     //\r
     // Adjust IndexNew according to real split.\r
     //\r
-    CopyMem (\r
-      ((UINT8 *)MemoryMap + (IndexNew + MaxSplitRecordCount - RealSplitRecordCount) * DescriptorSize),\r
-      ((UINT8 *)MemoryMap + IndexNew * DescriptorSize),\r
-      RealSplitRecordCount * DescriptorSize\r
-      );\r
+    if (MaxSplitRecordCount != RealSplitRecordCount) {\r
+      CopyMem (\r
+        ((UINT8 *)MemoryMap + (IndexNew + MaxSplitRecordCount - RealSplitRecordCount) * DescriptorSize),\r
+        ((UINT8 *)MemoryMap + IndexNew * DescriptorSize),\r
+        (RealSplitRecordCount + 1) * DescriptorSize\r
+        );\r
+    }\r
     IndexNew = IndexNew + MaxSplitRecordCount - RealSplitRecordCount;\r
     TotalSplitRecordCount += RealSplitRecordCount;\r
     IndexNew --;\r
@@ -744,7 +755,7 @@ SmmCoreGetMemoryMapMemoryAttributesTable (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 1) * mImagePropertiesPrivateData.ImageRecordCount;\r
+  AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 2) * mImagePropertiesPrivateData.ImageRecordCount;\r
 \r
   OldMemoryMapSize = *MemoryMapSize;\r
   Status = SmmCoreGetMemoryMap (MemoryMapSize, MemoryMap, MapKey, DescriptorSize, DescriptorVersion);\r