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