/** @file\r
UEFI Memory pool management functions.\r
\r
-Copyright (c) 2006 - 2014, 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) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
#include "DxeMain.h"\r
#include "Imem.h"\r
+#include "HeapGuard.h"\r
+\r
+STATIC EFI_LOCK mPoolMemoryLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);\r
\r
#define POOL_FREE_SIGNATURE SIGNATURE_32('p','f','r','0')\r
typedef struct {\r
} POOL_FREE;\r
\r
\r
-#define POOL_HEAD_SIGNATURE SIGNATURE_32('p','h','d','0')\r
+#define POOL_HEAD_SIGNATURE SIGNATURE_32('p','h','d','0')\r
+#define POOLPAGE_HEAD_SIGNATURE SIGNATURE_32('p','h','d','1')\r
typedef struct {\r
UINT32 Signature;\r
UINT32 Reserved;\r
// as we would in a strict power-of-2 sequence\r
//\r
STATIC CONST UINT16 mPoolSizeTable[] = {\r
- 64, 128, 192, 320, 512, 832, 1344, 2176, 3520, 5696, 9216, 14912, 24128\r
+ 128, 256, 384, 640, 1024, 1664, 2688, 4352, 7040, 11392, 18432, 29824\r
};\r
\r
#define SIZE_TO_LIST(a) (GetPoolIndexFromSize (a))\r
#define LIST_TO_SIZE(a) (mPoolSizeTable [a])\r
\r
-#define MAX_POOL_LIST (sizeof (mPoolSizeTable) / sizeof (mPoolSizeTable[0]))\r
+#define MAX_POOL_LIST (ARRAY_SIZE (mPoolSizeTable))\r
\r
#define MAX_POOL_SIZE (MAX_ADDRESS - POOL_OVERHEAD)\r
\r
//\r
LIST_ENTRY mPoolHeadList = INITIALIZE_LIST_HEAD_VARIABLE (mPoolHeadList);\r
\r
+/**\r
+ Get pool size table index from the specified size.\r
+\r
+ @param Size The specified size to get index from pool table.\r
+\r
+ @return The index of pool size table.\r
+\r
+**/\r
STATIC\r
UINTN\r
GetPoolIndexFromSize (\r
}\r
\r
//\r
- // MemoryType values in the range 0x80000000..0xFFFFFFFF are reserved for use by UEFI \r
- // OS loaders that are provided by operating system vendors\r
+ // MemoryType values in the range 0x80000000..0xFFFFFFFF are reserved for use by UEFI\r
+ // OS loaders that are provided by operating system vendors.\r
+ // MemoryType values in the range 0x70000000..0x7FFFFFFF are reserved for OEM use.\r
//\r
- if ((INT32)MemoryType < 0) {\r
+ if ((UINT32) MemoryType >= MEMORY_TYPE_OEM_RESERVED_MIN) {\r
\r
for (Link = mPoolHeadList.ForwardLink; Link != &mPoolHeadList; Link = Link->ForwardLink) {\r
Pool = CR(Link, POOL, Link, POOL_SIGNATURE);\r
}\r
}\r
\r
- Pool = CoreAllocatePoolI (EfiBootServicesData, sizeof (POOL));\r
+ Pool = CoreAllocatePoolI (EfiBootServicesData, sizeof (POOL), FALSE);\r
if (Pool == NULL) {\r
return NULL;\r
}\r
@param Buffer The address to return a pointer to the allocated\r
pool\r
\r
- @retval EFI_INVALID_PARAMETER PoolType not valid or Buffer is NULL. \r
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
+ PoolType is in the range EfiMaxMemoryType..0x6FFFFFFF.\r
+ PoolType is EfiPersistentMemory.\r
@retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.\r
@retval EFI_SUCCESS Pool successfully allocated.\r
\r
OUT VOID **Buffer\r
)\r
{\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
+ BOOLEAN NeedGuard;\r
\r
//\r
// If it's not a valid type, fail it\r
//\r
- if ((PoolType >= EfiMaxMemoryType && PoolType <= 0x7fffffff) ||\r
- PoolType == EfiConventionalMemory) {\r
+ if ((PoolType >= EfiMaxMemoryType && PoolType < MEMORY_TYPE_OEM_RESERVED_MIN) ||\r
+ (PoolType == EfiConventionalMemory) || (PoolType == EfiPersistentMemory)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
+ NeedGuard = IsPoolTypeToGuard (PoolType) && !mOnGuarding;\r
+\r
//\r
// Acquire the memory lock and make the allocation\r
//\r
- Status = CoreAcquireLockOrFail (&gMemoryLock);\r
+ Status = CoreAcquireLockOrFail (&mPoolMemoryLock);\r
if (EFI_ERROR (Status)) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- *Buffer = CoreAllocatePoolI (PoolType, Size);\r
- CoreReleaseMemoryLock ();\r
+ *Buffer = CoreAllocatePoolI (PoolType, Size, NeedGuard);\r
+ CoreReleaseLock (&mPoolMemoryLock);\r
return (*Buffer != NULL) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES;\r
}\r
\r
@param Buffer The address to return a pointer to the allocated\r
pool\r
\r
- @retval EFI_INVALID_PARAMETER PoolType not valid or Buffer is NULL. \r
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
+ PoolType is in the range EfiMaxMemoryType..0x6FFFFFFF.\r
+ PoolType is EfiPersistentMemory.\r
@retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.\r
@retval EFI_SUCCESS Pool successfully allocated.\r
\r
\r
Status = CoreInternalAllocatePool (PoolType, Size, Buffer);\r
if (!EFI_ERROR (Status)) {\r
- CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionAllocatePool, PoolType, Size, *Buffer);\r
+ CoreUpdateProfile (\r
+ (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0),\r
+ MemoryProfileActionAllocatePool,\r
+ PoolType,\r
+ Size,\r
+ *Buffer,\r
+ NULL\r
+ );\r
+ InstallMemoryAttributesTableOnMemoryAllocation (PoolType);\r
}\r
return Status;\r
}\r
\r
+/**\r
+ Internal function. Used by the pool functions to allocate pages\r
+ to back pool allocation requests.\r
+\r
+ @param PoolType The type of memory for the new pool pages\r
+ @param NoPages No of pages to allocate\r
+ @param Granularity Bits to align.\r
+ @param NeedGuard Flag to indicate Guard page is needed or not\r
+\r
+ @return The allocated memory, or NULL\r
+\r
+**/\r
+STATIC\r
+VOID *\r
+CoreAllocatePoolPagesI (\r
+ IN EFI_MEMORY_TYPE PoolType,\r
+ IN UINTN NoPages,\r
+ IN UINTN Granularity,\r
+ IN BOOLEAN NeedGuard\r
+ )\r
+{\r
+ VOID *Buffer;\r
+ EFI_STATUS Status;\r
+\r
+ Status = CoreAcquireLockOrFail (&gMemoryLock);\r
+ if (EFI_ERROR (Status)) {\r
+ return NULL;\r
+ }\r
+\r
+ Buffer = CoreAllocatePoolPages (PoolType, NoPages, Granularity, NeedGuard);\r
+ CoreReleaseMemoryLock ();\r
+\r
+ if (Buffer != NULL) {\r
+ if (NeedGuard) {\r
+ SetGuardForMemory ((EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, NoPages);\r
+ }\r
+ ApplyMemoryProtectionPolicy(EfiConventionalMemory, PoolType,\r
+ (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, EFI_PAGES_TO_SIZE (NoPages));\r
+ }\r
+ return Buffer;\r
+}\r
+\r
/**\r
Internal function to allocate pool of a particular type.\r
Caller must have the memory lock held\r
\r
@param PoolType Type of pool to allocate\r
@param Size The amount of pool to allocate\r
+ @param NeedGuard Flag to indicate Guard page is needed or not\r
\r
@return The allocate pool, or NULL\r
\r
VOID *\r
CoreAllocatePoolI (\r
IN EFI_MEMORY_TYPE PoolType,\r
- IN UINTN Size\r
+ IN UINTN Size,\r
+ IN BOOLEAN NeedGuard\r
)\r
{\r
POOL *Pool;\r
VOID *Buffer;\r
UINTN Index;\r
UINTN FSize;\r
- UINTN Offset;\r
+ UINTN Offset, MaxOffset;\r
UINTN NoPages;\r
UINTN Granularity;\r
+ BOOLEAN HasPoolTail;\r
+ BOOLEAN PageAsPool;\r
\r
- ASSERT_LOCKED (&gMemoryLock);\r
+ ASSERT_LOCKED (&mPoolMemoryLock);\r
\r
if (PoolType == EfiACPIReclaimMemory ||\r
PoolType == EfiACPIMemoryNVS ||\r
PoolType == EfiRuntimeServicesCode ||\r
PoolType == EfiRuntimeServicesData) {\r
\r
- Granularity = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT;\r
+ Granularity = RUNTIME_PAGE_ALLOCATION_GRANULARITY;\r
} else {\r
- Granularity = DEFAULT_PAGE_ALLOCATION;\r
+ Granularity = DEFAULT_PAGE_ALLOCATION_GRANULARITY;\r
}\r
\r
//\r
// Adjust the size by the pool header & tail overhead\r
//\r
\r
+ HasPoolTail = !(NeedGuard &&\r
+ ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) == 0));\r
+ PageAsPool = (IsHeapGuardEnabled (GUARD_HEAP_TYPE_FREED) && !mOnGuarding);\r
+\r
//\r
// Adjusting the Size to be of proper alignment so that\r
// we don't get an unaligned access fault later when\r
// If allocation is over max size, just allocate pages for the request\r
// (slow)\r
//\r
- if (Index >= SIZE_TO_LIST (Granularity)) {\r
- NoPages = EFI_SIZE_TO_PAGES(Size) + EFI_SIZE_TO_PAGES (Granularity) - 1;\r
+ if (Index >= SIZE_TO_LIST (Granularity) || NeedGuard || PageAsPool) {\r
+ if (!HasPoolTail) {\r
+ Size -= sizeof (POOL_TAIL);\r
+ }\r
+ NoPages = EFI_SIZE_TO_PAGES (Size) + EFI_SIZE_TO_PAGES (Granularity) - 1;\r
NoPages &= ~(UINTN)(EFI_SIZE_TO_PAGES (Granularity) - 1);\r
- Head = CoreAllocatePoolPages (PoolType, NoPages, Granularity);\r
+ Head = CoreAllocatePoolPagesI (PoolType, NoPages, Granularity, NeedGuard);\r
+ if (NeedGuard) {\r
+ Head = AdjustPoolHeadA ((EFI_PHYSICAL_ADDRESS)(UINTN)Head, NoPages, Size);\r
+ }\r
goto Done;\r
}\r
\r
//\r
if (IsListEmpty (&Pool->FreeList[Index])) {\r
\r
+ Offset = LIST_TO_SIZE (Index);\r
+ MaxOffset = Granularity;\r
+\r
+ //\r
+ // Check the bins holding larger blocks, and carve one up if needed\r
+ //\r
+ while (++Index < SIZE_TO_LIST (Granularity)) {\r
+ if (!IsListEmpty (&Pool->FreeList[Index])) {\r
+ Free = CR (Pool->FreeList[Index].ForwardLink, POOL_FREE, Link, POOL_FREE_SIGNATURE);\r
+ RemoveEntryList (&Free->Link);\r
+ NewPage = (VOID *) Free;\r
+ MaxOffset = LIST_TO_SIZE (Index);\r
+ goto Carve;\r
+ }\r
+ }\r
+\r
//\r
// Get another page\r
//\r
- NewPage = CoreAllocatePoolPages(PoolType, EFI_SIZE_TO_PAGES (Granularity), Granularity);\r
+ NewPage = CoreAllocatePoolPagesI (PoolType, EFI_SIZE_TO_PAGES (Granularity),\r
+ Granularity, NeedGuard);\r
if (NewPage == NULL) {\r
goto Done;\r
}\r
//\r
// Serve the allocation request from the head of the allocated block\r
//\r
+Carve:\r
Head = (POOL_HEAD *) NewPage;\r
- Offset = LIST_TO_SIZE (Index);\r
\r
//\r
// Carve up remaining space into free pool blocks\r
//\r
- Index = SIZE_TO_LIST (Granularity) - 1;\r
- while (Offset < Granularity) {\r
+ Index--;\r
+ while (Offset < MaxOffset) {\r
ASSERT (Index < MAX_POOL_LIST);\r
FSize = LIST_TO_SIZE(Index);\r
\r
- while (Offset + FSize <= Granularity) {\r
+ while (Offset + FSize <= MaxOffset) {\r
Free = (POOL_FREE *) &NewPage[Offset];\r
Free->Signature = POOL_FREE_SIGNATURE;\r
Free->Index = (UINT32)Index;\r
InsertHeadList (&Pool->FreeList[Index], &Free->Link);\r
Offset += FSize;\r
}\r
-\r
Index -= 1;\r
}\r
\r
- ASSERT (Offset == Granularity);\r
+ ASSERT (Offset == MaxOffset);\r
goto Done;\r
}\r
\r
\r
if (Head != NULL) {\r
\r
+ //\r
+ // Account the allocation\r
+ //\r
+ Pool->Used += Size;\r
+\r
//\r
// If we have a pool buffer, fill in the header & tail info\r
//\r
- Head->Signature = POOL_HEAD_SIGNATURE;\r
+ Head->Signature = (PageAsPool) ? POOLPAGE_HEAD_SIGNATURE : POOL_HEAD_SIGNATURE;\r
Head->Size = Size;\r
Head->Type = (EFI_MEMORY_TYPE) PoolType;\r
- Tail = HEAD_TO_TAIL (Head);\r
- Tail->Signature = POOL_TAIL_SIGNATURE;\r
- Tail->Size = Size;\r
Buffer = Head->Data;\r
- DEBUG_CLEAR_MEMORY (Buffer, Size - POOL_OVERHEAD);\r
+\r
+ if (HasPoolTail) {\r
+ Tail = HEAD_TO_TAIL (Head);\r
+ Tail->Signature = POOL_TAIL_SIGNATURE;\r
+ Tail->Size = Size;\r
+\r
+ Size -= POOL_OVERHEAD;\r
+ } else {\r
+ Size -= SIZE_OF_POOL_HEAD;\r
+ }\r
+\r
+ DEBUG_CLEAR_MEMORY (Buffer, Size);\r
\r
DEBUG ((\r
DEBUG_POOL,\r
"AllocatePoolI: Type %x, Addr %p (len %lx) %,ld\n", PoolType,\r
Buffer,\r
- (UINT64)(Size - POOL_OVERHEAD),\r
+ (UINT64)Size,\r
(UINT64) Pool->Used\r
));\r
\r
- //\r
- // Account the allocation\r
- //\r
- Pool->Used += Size;\r
\r
} else {\r
DEBUG ((DEBUG_ERROR | DEBUG_POOL, "AllocatePool: failed to allocate %ld bytes\n", (UINT64) Size));\r
Frees pool.\r
\r
@param Buffer The allocated pool entry to free\r
+ @param PoolType Pointer to pool type\r
\r
@retval EFI_INVALID_PARAMETER Buffer is not a valid value.\r
@retval EFI_SUCCESS Pool successfully freed.\r
EFI_STATUS\r
EFIAPI\r
CoreInternalFreePool (\r
- IN VOID *Buffer\r
+ IN VOID *Buffer,\r
+ OUT EFI_MEMORY_TYPE *PoolType OPTIONAL\r
)\r
{\r
EFI_STATUS Status;\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- CoreAcquireMemoryLock ();\r
- Status = CoreFreePoolI (Buffer);\r
- CoreReleaseMemoryLock ();\r
+ CoreAcquireLock (&mPoolMemoryLock);\r
+ Status = CoreFreePoolI (Buffer, PoolType);\r
+ CoreReleaseLock (&mPoolMemoryLock);\r
return Status;\r
}\r
\r
IN VOID *Buffer\r
)\r
{\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
+ EFI_MEMORY_TYPE PoolType;\r
\r
- Status = CoreInternalFreePool (Buffer);\r
+ Status = CoreInternalFreePool (Buffer, &PoolType);\r
if (!EFI_ERROR (Status)) {\r
- CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionFreePool, (EFI_MEMORY_TYPE) 0, 0, Buffer);\r
+ CoreUpdateProfile (\r
+ (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0),\r
+ MemoryProfileActionFreePool,\r
+ PoolType,\r
+ 0,\r
+ Buffer,\r
+ NULL\r
+ );\r
+ InstallMemoryAttributesTableOnMemoryAllocation (PoolType);\r
}\r
return Status;\r
}\r
\r
+/**\r
+ Internal function. Frees pool pages allocated via CoreAllocatePoolPagesI().\r
+\r
+ @param PoolType The type of memory for the pool pages\r
+ @param Memory The base address to free\r
+ @param NoPages The number of pages to free\r
+\r
+**/\r
+STATIC\r
+VOID\r
+CoreFreePoolPagesI (\r
+ IN EFI_MEMORY_TYPE PoolType,\r
+ IN EFI_PHYSICAL_ADDRESS Memory,\r
+ IN UINTN NoPages\r
+ )\r
+{\r
+ CoreAcquireMemoryLock ();\r
+ CoreFreePoolPages (Memory, NoPages);\r
+ CoreReleaseMemoryLock ();\r
+\r
+ GuardFreedPagesChecked (Memory, NoPages);\r
+ ApplyMemoryProtectionPolicy (PoolType, EfiConventionalMemory,\r
+ (EFI_PHYSICAL_ADDRESS)(UINTN)Memory, EFI_PAGES_TO_SIZE (NoPages));\r
+}\r
+\r
+/**\r
+ Internal function. Frees guarded pool pages.\r
+\r
+ @param PoolType The type of memory for the pool pages\r
+ @param Memory The base address to free\r
+ @param NoPages The number of pages to free\r
+\r
+**/\r
+STATIC\r
+VOID\r
+CoreFreePoolPagesWithGuard (\r
+ IN EFI_MEMORY_TYPE PoolType,\r
+ IN EFI_PHYSICAL_ADDRESS Memory,\r
+ IN UINTN NoPages\r
+ )\r
+{\r
+ EFI_PHYSICAL_ADDRESS MemoryGuarded;\r
+ UINTN NoPagesGuarded;\r
+\r
+ MemoryGuarded = Memory;\r
+ NoPagesGuarded = NoPages;\r
+\r
+ AdjustMemoryF (&Memory, &NoPages);\r
+ //\r
+ // It's safe to unset Guard page inside memory lock because there should\r
+ // be no memory allocation occurred in updating memory page attribute at\r
+ // this point. And unsetting Guard page before free will prevent Guard\r
+ // page just freed back to pool from being allocated right away before\r
+ // marking it usable (from non-present to present).\r
+ //\r
+ UnsetGuardForMemory (MemoryGuarded, NoPagesGuarded);\r
+ if (NoPages > 0) {\r
+ CoreFreePoolPagesI (PoolType, Memory, NoPages);\r
+ }\r
+}\r
+\r
/**\r
Internal function to free a pool entry.\r
Caller must have the memory lock held\r
\r
@param Buffer The allocated pool entry to free\r
+ @param PoolType Pointer to pool type\r
\r
@retval EFI_INVALID_PARAMETER Buffer not valid\r
@retval EFI_SUCCESS Buffer successfully freed.\r
**/\r
EFI_STATUS\r
CoreFreePoolI (\r
- IN VOID *Buffer\r
+ IN VOID *Buffer,\r
+ OUT EFI_MEMORY_TYPE *PoolType OPTIONAL\r
)\r
{\r
POOL *Pool;\r
UINTN Offset;\r
BOOLEAN AllFree;\r
UINTN Granularity;\r
+ BOOLEAN IsGuarded;\r
+ BOOLEAN HasPoolTail;\r
+ BOOLEAN PageAsPool;\r
\r
ASSERT(Buffer != NULL);\r
//\r
// Get the head & tail of the pool entry\r
//\r
- Head = CR (Buffer, POOL_HEAD, Data, POOL_HEAD_SIGNATURE);\r
+ Head = BASE_CR (Buffer, POOL_HEAD, Data);\r
ASSERT(Head != NULL);\r
\r
- if (Head->Signature != POOL_HEAD_SIGNATURE) {\r
+ if (Head->Signature != POOL_HEAD_SIGNATURE &&\r
+ Head->Signature != POOLPAGE_HEAD_SIGNATURE) {\r
+ ASSERT (Head->Signature == POOL_HEAD_SIGNATURE ||\r
+ Head->Signature == POOLPAGE_HEAD_SIGNATURE);\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- Tail = HEAD_TO_TAIL (Head);\r
- ASSERT(Tail != NULL);\r
+ IsGuarded = IsPoolTypeToGuard (Head->Type) &&\r
+ IsMemoryGuarded ((EFI_PHYSICAL_ADDRESS)(UINTN)Head);\r
+ HasPoolTail = !(IsGuarded &&\r
+ ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) == 0));\r
+ PageAsPool = (Head->Signature == POOLPAGE_HEAD_SIGNATURE);\r
\r
- //\r
- // Debug\r
- //\r
- ASSERT (Tail->Signature == POOL_TAIL_SIGNATURE);\r
- ASSERT (Head->Size == Tail->Size);\r
- ASSERT_LOCKED (&gMemoryLock);\r
+ if (HasPoolTail) {\r
+ Tail = HEAD_TO_TAIL (Head);\r
+ ASSERT (Tail != NULL);\r
\r
- if (Tail->Signature != POOL_TAIL_SIGNATURE) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
+ //\r
+ // Debug\r
+ //\r
+ ASSERT (Tail->Signature == POOL_TAIL_SIGNATURE);\r
+ ASSERT (Head->Size == Tail->Size);\r
\r
- if (Head->Size != Tail->Size) {\r
- return EFI_INVALID_PARAMETER;\r
+ if (Tail->Signature != POOL_TAIL_SIGNATURE) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Head->Size != Tail->Size) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
}\r
\r
+ ASSERT_LOCKED (&mPoolMemoryLock);\r
+\r
//\r
// Determine the pool type and account for it\r
//\r
Head->Type == EfiRuntimeServicesCode ||\r
Head->Type == EfiRuntimeServicesData) {\r
\r
- Granularity = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT;\r
+ Granularity = RUNTIME_PAGE_ALLOCATION_GRANULARITY;\r
} else {\r
- Granularity = DEFAULT_PAGE_ALLOCATION;\r
+ Granularity = DEFAULT_PAGE_ALLOCATION_GRANULARITY;\r
+ }\r
+\r
+ if (PoolType != NULL) {\r
+ *PoolType = Head->Type;\r
}\r
\r
//\r
//\r
// If it's not on the list, it must be pool pages\r
//\r
- if (Index >= SIZE_TO_LIST (Granularity)) {\r
+ if (Index >= SIZE_TO_LIST (Granularity) || IsGuarded || PageAsPool) {\r
\r
//\r
// Return the memory pages back to free memory\r
//\r
- NoPages = EFI_SIZE_TO_PAGES(Size) + EFI_SIZE_TO_PAGES (Granularity) - 1;\r
+ NoPages = EFI_SIZE_TO_PAGES (Size) + EFI_SIZE_TO_PAGES (Granularity) - 1;\r
NoPages &= ~(UINTN)(EFI_SIZE_TO_PAGES (Granularity) - 1);\r
- CoreFreePoolPages ((EFI_PHYSICAL_ADDRESS) (UINTN) Head, NoPages);\r
+ if (IsGuarded) {\r
+ Head = AdjustPoolHeadF ((EFI_PHYSICAL_ADDRESS)(UINTN)Head);\r
+ CoreFreePoolPagesWithGuard (\r
+ Pool->MemoryType,\r
+ (EFI_PHYSICAL_ADDRESS)(UINTN)Head,\r
+ NoPages\r
+ );\r
+ } else {\r
+ CoreFreePoolPagesI (\r
+ Pool->MemoryType,\r
+ (EFI_PHYSICAL_ADDRESS)(UINTN)Head,\r
+ NoPages\r
+ );\r
+ }\r
\r
} else {\r
\r
//\r
// Free the page\r
//\r
- CoreFreePoolPages ((EFI_PHYSICAL_ADDRESS) (UINTN)NewPage, EFI_SIZE_TO_PAGES (Granularity));\r
+ CoreFreePoolPagesI (Pool->MemoryType, (EFI_PHYSICAL_ADDRESS) (UINTN)NewPage,\r
+ EFI_SIZE_TO_PAGES (Granularity));\r
}\r
}\r
}\r
\r
//\r
- // If this is an OS specific memory type, then check to see if the last\r
+ // If this is an OS/OEM specific memory type, then check to see if the last\r
// portion of that memory type has been freed. If it has, then free the\r
// list entry for that memory type\r
//\r
- if ((INT32)Pool->MemoryType < 0 && Pool->Used == 0) {\r
+ if (((UINT32) Pool->MemoryType >= MEMORY_TYPE_OEM_RESERVED_MIN) && Pool->Used == 0) {\r
RemoveEntryList (&Pool->Link);\r
- CoreFreePoolI (Pool);\r
+ CoreFreePoolI (Pool, NULL);\r
}\r
\r
return EFI_SUCCESS;\r