]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/PiSmmCore/HeapGuard.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Core / PiSmmCore / HeapGuard.c
index c5ffb263420e0a3d37e1de9d9825c96ce87f1a17..29cd00f3897d19ab6029208331bf536e3ef032ac 100644 (file)
@@ -1,14 +1,8 @@
 /** @file\r
   UEFI Heap Guard functions.\r
 \r
-Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution.  The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2017-2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -73,7 +67,7 @@ SetBits (
   StartBit  = (UINTN)GUARDED_HEAP_MAP_ENTRY_BIT_INDEX (Address);\r
   EndBit    = (StartBit + BitNumber - 1) % GUARDED_HEAP_MAP_ENTRY_BITS;\r
 \r
-  if ((StartBit + BitNumber) > GUARDED_HEAP_MAP_ENTRY_BITS) {\r
+  if ((StartBit + BitNumber) >= GUARDED_HEAP_MAP_ENTRY_BITS) {\r
     Msbs    = (GUARDED_HEAP_MAP_ENTRY_BITS - StartBit) %\r
               GUARDED_HEAP_MAP_ENTRY_BITS;\r
     Lsbs    = (EndBit + 1) % GUARDED_HEAP_MAP_ENTRY_BITS;\r
@@ -126,7 +120,7 @@ ClearBits (
   StartBit  = (UINTN)GUARDED_HEAP_MAP_ENTRY_BIT_INDEX (Address);\r
   EndBit    = (StartBit + BitNumber - 1) % GUARDED_HEAP_MAP_ENTRY_BITS;\r
 \r
-  if ((StartBit + BitNumber) > GUARDED_HEAP_MAP_ENTRY_BITS) {\r
+  if ((StartBit + BitNumber) >= GUARDED_HEAP_MAP_ENTRY_BITS) {\r
     Msbs    = (GUARDED_HEAP_MAP_ENTRY_BITS - StartBit) %\r
               GUARDED_HEAP_MAP_ENTRY_BITS;\r
     Lsbs    = (EndBit + 1) % GUARDED_HEAP_MAP_ENTRY_BITS;\r
@@ -191,10 +185,14 @@ GetBits (
     Lsbs = 0;\r
   }\r
 \r
-  Result    = RShiftU64 ((*BitMap), StartBit) & (LShiftU64 (1, Msbs) - 1);\r
-  if (Lsbs > 0) {\r
-    BitMap  += 1;\r
-    Result  |= LShiftU64 ((*BitMap) & (LShiftU64 (1, Lsbs) - 1), Msbs);\r
+  if (StartBit == 0 && BitNumber == GUARDED_HEAP_MAP_ENTRY_BITS) {\r
+    Result = *BitMap;\r
+  } else {\r
+    Result    = RShiftU64((*BitMap), StartBit) & (LShiftU64(1, Msbs) - 1);\r
+    if (Lsbs > 0) {\r
+      BitMap  += 1;\r
+      Result  |= LShiftU64 ((*BitMap) & (LShiftU64 (1, Lsbs) - 1), Msbs);\r
+    }\r
   }\r
 \r
   return Result;\r
@@ -251,8 +249,8 @@ FindGuardedMemoryMap (
   //\r
   // Adjust current map table depth according to the address to access\r
   //\r
-  while (mMapLevel < GUARDED_HEAP_MAP_TABLE_DEPTH\r
-         &&\r
+  while (AllocMapUnit &&\r
+         mMapLevel < GUARDED_HEAP_MAP_TABLE_DEPTH &&\r
          RShiftU64 (\r
            Address,\r
            mLevelShift[GUARDED_HEAP_MAP_TABLE_DEPTH - mMapLevel - 1]\r
@@ -451,51 +449,6 @@ GetGuardMapBit (
   return 0;\r
 }\r
 \r
-/**\r
-  Set the bit in bitmap table for the given address.\r
-\r
-  @param[in]  Address     The address to set for.\r
-\r
-  @return VOID.\r
-**/\r
-VOID\r
-EFIAPI\r
-SetGuardMapBit (\r
-  IN EFI_PHYSICAL_ADDRESS    Address\r
-  )\r
-{\r
-  UINT64        *GuardMap;\r
-  UINT64        BitMask;\r
-\r
-  FindGuardedMemoryMap (Address, TRUE, &GuardMap);\r
-  if (GuardMap != NULL) {\r
-    BitMask = LShiftU64 (1, GUARDED_HEAP_MAP_ENTRY_BIT_INDEX (Address));\r
-    *GuardMap |= BitMask;\r
-  }\r
-}\r
-\r
-/**\r
-  Clear the bit in bitmap table for the given address.\r
-\r
-  @param[in]  Address     The address to clear for.\r
-\r
-  @return VOID.\r
-**/\r
-VOID\r
-EFIAPI\r
-ClearGuardMapBit (\r
-  IN EFI_PHYSICAL_ADDRESS    Address\r
-  )\r
-{\r
-  UINT64        *GuardMap;\r
-  UINT64        BitMask;\r
-\r
-  FindGuardedMemoryMap (Address, TRUE, &GuardMap);\r
-  if (GuardMap != NULL) {\r
-    BitMask = LShiftU64 (1, GUARDED_HEAP_MAP_ENTRY_BIT_INDEX (Address));\r
-    *GuardMap &= ~BitMask;\r
-  }\r
-}\r
 \r
 /**\r
   Check to see if the page at the given address is a Guard page or not.\r
@@ -522,39 +475,7 @@ IsGuardPage (
   return ((BitMap == BIT0) || (BitMap == BIT2) || (BitMap == (BIT2 | BIT0)));\r
 }\r
 \r
-/**\r
-  Check to see if the page at the given address is a head Guard page or not.\r
 \r
-  @param[in]  Address     The address to check for.\r
-\r
-  @return TRUE  The page at Address is a head Guard page.\r
-  @return FALSE The page at Address is not a head Guard page.\r
-**/\r
-BOOLEAN\r
-EFIAPI\r
-IsHeadGuard (\r
-  IN EFI_PHYSICAL_ADDRESS    Address\r
-  )\r
-{\r
-  return (GetGuardedMemoryBits (Address, 2) == BIT1);\r
-}\r
-\r
-/**\r
-  Check to see if the page at the given address is a tail Guard page or not.\r
-\r
-  @param[in]  Address     The address to check for.\r
-\r
-  @return TRUE  The page at Address is a tail Guard page.\r
-  @return FALSE The page at Address is not a tail Guard page.\r
-**/\r
-BOOLEAN\r
-EFIAPI\r
-IsTailGuard (\r
-  IN EFI_PHYSICAL_ADDRESS    Address\r
-  )\r
-{\r
-  return (GetGuardedMemoryBits (Address - EFI_PAGE_SIZE, 2) == BIT0);\r
-}\r
 \r
 /**\r
   Check to see if the page at the given address is guarded or not.\r
@@ -588,14 +509,17 @@ SetGuardPage (
   IN  EFI_PHYSICAL_ADDRESS      BaseAddress\r
   )\r
 {\r
+  EFI_STATUS      Status;\r
+\r
   if (mSmmMemoryAttribute != NULL) {\r
     mOnGuarding = TRUE;\r
-    mSmmMemoryAttribute->SetMemoryAttributes (\r
-                           mSmmMemoryAttribute,\r
-                           BaseAddress,\r
-                           EFI_PAGE_SIZE,\r
-                           EFI_MEMORY_RP\r
-                           );\r
+    Status = mSmmMemoryAttribute->SetMemoryAttributes (\r
+                                    mSmmMemoryAttribute,\r
+                                    BaseAddress,\r
+                                    EFI_PAGE_SIZE,\r
+                                    EFI_MEMORY_RP\r
+                                    );\r
+    ASSERT_EFI_ERROR (Status);\r
     mOnGuarding = FALSE;\r
   }\r
 }\r
@@ -615,14 +539,17 @@ UnsetGuardPage (
   IN  EFI_PHYSICAL_ADDRESS      BaseAddress\r
   )\r
 {\r
+  EFI_STATUS      Status;\r
+\r
   if (mSmmMemoryAttribute != NULL) {\r
     mOnGuarding = TRUE;\r
-    mSmmMemoryAttribute->ClearMemoryAttributes (\r
-                           mSmmMemoryAttribute,\r
-                           BaseAddress,\r
-                           EFI_PAGE_SIZE,\r
-                           EFI_MEMORY_RP\r
-                           );\r
+    Status = mSmmMemoryAttribute->ClearMemoryAttributes (\r
+                                    mSmmMemoryAttribute,\r
+                                    BaseAddress,\r
+                                    EFI_PAGE_SIZE,\r
+                                    EFI_MEMORY_RP\r
+                                    );\r
+    ASSERT_EFI_ERROR (Status);\r
     mOnGuarding = FALSE;\r
   }\r
 }\r
@@ -854,69 +781,7 @@ UnsetGuardForMemory (
   ClearGuardedMemoryBits(Memory, NumberOfPages);\r
 }\r
 \r
-/**\r
-  Adjust address of free memory according to existing and/or required Guard.\r
-\r
-  This function will check if there're existing Guard pages of adjacent\r
-  memory blocks, and try to use it as the Guard page of the memory to be\r
-  allocated.\r
 \r
-  @param[in]  Start           Start address of free memory block.\r
-  @param[in]  Size            Size of free memory block.\r
-  @param[in]  SizeRequested   Size of memory to allocate.\r
-\r
-  @return The end address of memory block found.\r
-  @return 0 if no enough space for the required size of memory and its Guard.\r
-**/\r
-UINT64\r
-AdjustMemoryS (\r
-  IN UINT64                  Start,\r
-  IN UINT64                  Size,\r
-  IN UINT64                  SizeRequested\r
-  )\r
-{\r
-  UINT64  Target;\r
-\r
-  //\r
-  // UEFI spec requires that allocated pool must be 8-byte aligned. If it's\r
-  // indicated to put the pool near the Tail Guard, we need extra bytes to\r
-  // make sure alignment of the returned pool address.\r
-  //\r
-  if ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) == 0) {\r
-    SizeRequested = ALIGN_VALUE(SizeRequested, 8);\r
-  }\r
-\r
-  Target = Start + Size - SizeRequested;\r
-\r
-  //\r
-  // At least one more page needed for Guard page.\r
-  //\r
-  if (Size < (SizeRequested + EFI_PAGES_TO_SIZE (1))) {\r
-    return 0;\r
-  }\r
-\r
-  if (!IsGuardPage (Start + Size)) {\r
-    // No Guard at tail to share. One more page is needed.\r
-    Target -= EFI_PAGES_TO_SIZE (1);\r
-  }\r
-\r
-  // Out of range?\r
-  if (Target < Start) {\r
-    return 0;\r
-  }\r
-\r
-  // At the edge?\r
-  if (Target == Start) {\r
-    if (!IsGuardPage (Target - EFI_PAGES_TO_SIZE (1))) {\r
-      // No enough space for a new head Guard if no Guard at head to share.\r
-      return 0;\r
-    }\r
-  }\r
-\r
-  // OK, we have enough pages for memory and its Guards. Return the End of the\r
-  // free space.\r
-  return Target + SizeRequested - 1;\r
-}\r
 \r
 /**\r
   Adjust the start address and number of pages to free according to Guard.\r
@@ -940,6 +805,7 @@ AdjustMemoryF (
   EFI_PHYSICAL_ADDRESS  MemoryToTest;\r
   UINTN                 PagesToFree;\r
   UINT64                GuardBitmap;\r
+  UINT64                Attributes;\r
 \r
   if (Memory == NULL || NumberOfPages == NULL || *NumberOfPages == 0) {\r
     return;\r
@@ -948,6 +814,27 @@ AdjustMemoryF (
   Start = *Memory;\r
   PagesToFree = *NumberOfPages;\r
 \r
+  //\r
+  // In case the memory to free is marked as read-only (e.g. EfiRuntimeServicesCode).\r
+  //\r
+  if (mSmmMemoryAttribute != NULL) {\r
+    Attributes = 0;\r
+    mSmmMemoryAttribute->GetMemoryAttributes (\r
+                           mSmmMemoryAttribute,\r
+                           Start,\r
+                           EFI_PAGES_TO_SIZE (PagesToFree),\r
+                           &Attributes\r
+                           );\r
+    if ((Attributes & EFI_MEMORY_RO) != 0) {\r
+      mSmmMemoryAttribute->ClearMemoryAttributes (\r
+                             mSmmMemoryAttribute,\r
+                             Start,\r
+                             EFI_PAGES_TO_SIZE (PagesToFree),\r
+                             EFI_MEMORY_RO\r
+                             );\r
+    }\r
+  }\r
+\r
   //\r
   // Head Guard must be one page before, if any.\r
   //\r
@@ -1020,36 +907,6 @@ AdjustMemoryF (
   *NumberOfPages  = PagesToFree;\r
 }\r
 \r
-/**\r
-  Adjust the base and number of pages to really allocate according to Guard.\r
-\r
-  @param[in,out]  Memory          Base address of free memory.\r
-  @param[in,out]  NumberOfPages   Size of memory to allocate.\r
-\r
-  @return VOID.\r
-**/\r
-VOID\r
-AdjustMemoryA (\r
-  IN OUT EFI_PHYSICAL_ADDRESS    *Memory,\r
-  IN OUT UINTN                   *NumberOfPages\r
-  )\r
-{\r
-  //\r
-  // FindFreePages() has already taken the Guard into account. It's safe to\r
-  // adjust the start address and/or number of pages here, to make sure that\r
-  // the Guards are also "allocated".\r
-  //\r
-  if (!IsGuardPage (*Memory + EFI_PAGES_TO_SIZE (*NumberOfPages))) {\r
-    // No tail Guard, add one.\r
-    *NumberOfPages += 1;\r
-  }\r
-\r
-  if (!IsGuardPage (*Memory - EFI_PAGE_SIZE)) {\r
-    // No head Guard, add one.\r
-    *Memory        -= EFI_PAGE_SIZE;\r
-    *NumberOfPages += 1;\r
-  }\r
-}\r
 \r
 /**\r
   Adjust the pool head position to make sure the Guard page is adjavent to\r