/** @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
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
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
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
//\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
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
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
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
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
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
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
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
*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