]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/PiSmmCore/HeapGuard.c
MdeModulePkg/PiSmmCore: Control S3 related functionality through flag.
[mirror_edk2.git] / MdeModulePkg / Core / PiSmmCore / HeapGuard.c
index 04fa1747a1e15ea9397ee85762744d951b163f8a..f7ae9ae28686d1949f9e4bf9e6daba58e4fc0297 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   UEFI Heap Guard functions.\r
 \r
-Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2017-2018, 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
@@ -73,7 +73,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 +126,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 +191,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 +255,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 +455,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 +481,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 +515,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 +545,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,60 +787,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
-  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
@@ -931,6 +811,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
@@ -939,6 +820,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
@@ -1011,36 +913,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
@@ -1060,7 +932,7 @@ AdjustPoolHeadA (
   IN UINTN                   Size\r
   )\r
 {\r
-  if ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) != 0) {\r
+  if (Memory == 0 || (PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) != 0) {\r
     //\r
     // Pool head is put near the head Guard\r
     //\r
@@ -1070,6 +942,7 @@ AdjustPoolHeadA (
   //\r
   // Pool head is put near the tail Guard\r
   //\r
+  Size = ALIGN_VALUE (Size, 8);\r
   return (VOID *)(UINTN)(Memory + EFI_PAGES_TO_SIZE (NoPages) - Size);\r
 }\r
 \r
@@ -1085,7 +958,7 @@ AdjustPoolHeadF (
   IN EFI_PHYSICAL_ADDRESS    Memory\r
   )\r
 {\r
-  if ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) != 0) {\r
+  if (Memory == 0 || (PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) != 0) {\r
     //\r
     // Pool head is put near the head Guard\r
     //\r
@@ -1195,6 +1068,10 @@ SmmInternalFreePagesExWithGuard (
   EFI_PHYSICAL_ADDRESS    MemoryToFree;\r
   UINTN                   PagesToFree;\r
 \r
+  if (((Memory & EFI_PAGE_MASK) != 0) || (Memory == 0) || (NumberOfPages == 0)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
   MemoryToFree  = Memory;\r
   PagesToFree   = NumberOfPages;\r
 \r