]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
MdeModulePkg/DxeIpl: Implement NULL pointer detection
[mirror_edk2.git] / MdeModulePkg / Core / DxeIplPeim / X64 / VirtualMemory.c
index 48150be4e1c8bdfa724399c87ab330e8198108a0..a10dea25fd7fd2c65dfa7c6f3bf51426922ac1e1 100644 (file)
@@ -31,6 +31,68 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include "DxeIpl.h"\r
 #include "VirtualMemory.h"\r
 \r
+/**\r
+   Clear legacy memory located at the first 4K-page, if available.\r
+\r
+   This function traverses the whole HOB list to check if memory from 0 to 4095\r
+   exists and has not been allocated, and then clear it if so.\r
+\r
+   @param HoStart                   The start of HobList passed to DxeCore.\r
+\r
+**/\r
+VOID\r
+ClearFirst4KPage (\r
+  IN  VOID *HobStart\r
+  )\r
+{\r
+  EFI_PEI_HOB_POINTERS          RscHob;\r
+  EFI_PEI_HOB_POINTERS          MemHob;\r
+  BOOLEAN                       DoClear;\r
+\r
+  RscHob.Raw = HobStart;\r
+  MemHob.Raw = HobStart;\r
+  DoClear = FALSE;\r
+\r
+  //\r
+  // Check if page 0 exists and free\r
+  //\r
+  while ((RscHob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,\r
+                                   RscHob.Raw)) != NULL) {\r
+    if (RscHob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&\r
+        RscHob.ResourceDescriptor->PhysicalStart == 0) {\r
+      DoClear = TRUE;\r
+      //\r
+      // Make sure memory at 0-4095 has not been allocated.\r
+      //\r
+      while ((MemHob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION,\r
+                                       MemHob.Raw)) != NULL) {\r
+        if (MemHob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress\r
+            < EFI_PAGE_SIZE) {\r
+          DoClear = FALSE;\r
+          break;\r
+        }\r
+        MemHob.Raw = GET_NEXT_HOB (MemHob);\r
+      }\r
+      break;\r
+    }\r
+    RscHob.Raw = GET_NEXT_HOB (RscHob);\r
+  }\r
+\r
+  if (DoClear) {\r
+    DEBUG ((DEBUG_INFO, "Clearing first 4K-page!\r\n"));\r
+    SetMem (NULL, EFI_PAGE_SIZE, 0);\r
+  }\r
+\r
+  return;\r
+}\r
+\r
+BOOLEAN\r
+IsNullDetectionEnabled (\r
+  VOID\r
+  )\r
+{\r
+  return ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT0) != 0);\r
+}\r
 \r
 /**\r
   Enable Execute Disable Bit.\r
@@ -90,8 +152,16 @@ Split2MPageTo4K (
     //\r
     PageTableEntry->Uint64 = (UINT64) PhysicalAddress4K | AddressEncMask;\r
     PageTableEntry->Bits.ReadWrite = 1;\r
-    PageTableEntry->Bits.Present = 1;\r
-    if ((PhysicalAddress4K >= StackBase) && (PhysicalAddress4K < StackBase + StackSize)) {\r
+\r
+    if (IsNullDetectionEnabled () && PhysicalAddress4K == 0) {\r
+      PageTableEntry->Bits.Present = 0;\r
+    } else {\r
+      PageTableEntry->Bits.Present = 1;\r
+    }\r
+\r
+    if (PcdGetBool (PcdSetNxForStack)\r
+        && (PhysicalAddress4K >= StackBase)\r
+        && (PhysicalAddress4K < StackBase + StackSize)) {\r
       //\r
       // Set Nx bit for stack.\r
       //\r
@@ -137,9 +207,12 @@ Split1GPageTo2M (
 \r
   PhysicalAddress2M = PhysicalAddress;\r
   for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress2M += SIZE_2MB) {\r
-    if ((PhysicalAddress2M < StackBase + StackSize) && ((PhysicalAddress2M + SIZE_2MB) > StackBase)) {\r
+    if ((IsNullDetectionEnabled () && PhysicalAddress2M == 0)\r
+        || (PcdGetBool (PcdSetNxForStack)\r
+            && (PhysicalAddress2M < StackBase + StackSize)\r
+            && ((PhysicalAddress2M + SIZE_2MB) > StackBase))) {\r
       //\r
-      // Need to split this 2M page that covers stack range.\r
+      // Need to split this 2M page that covers NULL or stack range.\r
       //\r
       Split2MPageTo4K (PhysicalAddress2M, (UINT64 *) PageDirectoryEntry, StackBase, StackSize);\r
     } else {\r
@@ -279,7 +352,10 @@ CreateIdentityMappingPageTables (
       PageDirectory1GEntry = (VOID *) PageDirectoryPointerEntry;\r
     \r
       for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress += SIZE_1GB) {\r
-        if (PcdGetBool (PcdSetNxForStack) && (PageAddress < StackBase + StackSize) && ((PageAddress + SIZE_1GB) > StackBase)) {\r
+        if ((IsNullDetectionEnabled () && PageAddress == 0)\r
+            || (PcdGetBool (PcdSetNxForStack)\r
+                && (PageAddress < StackBase + StackSize)\r
+                && ((PageAddress + SIZE_1GB) > StackBase))) {\r
           Split1GPageTo2M (PageAddress, (UINT64 *) PageDirectory1GEntry, StackBase, StackSize);\r
         } else {\r
           //\r
@@ -308,9 +384,12 @@ CreateIdentityMappingPageTables (
         PageDirectoryPointerEntry->Bits.Present = 1;\r
 \r
         for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += SIZE_2MB) {\r
-          if (PcdGetBool (PcdSetNxForStack) && (PageAddress < StackBase + StackSize) && ((PageAddress + SIZE_2MB) > StackBase)) {\r
+          if ((IsNullDetectionEnabled () && PageAddress == 0)\r
+              || (PcdGetBool (PcdSetNxForStack)\r
+                  && (PageAddress < StackBase + StackSize)\r
+                  && ((PageAddress + SIZE_2MB) > StackBase))) {\r
             //\r
-            // Need to split this 2M page that covers stack range.\r
+            // Need to split this 2M page that covers NULL or stack range.\r
             //\r
             Split2MPageTo4K (PageAddress, (UINT64 *) PageDirectoryEntry, StackBase, StackSize);\r
           } else {\r