X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FCore%2FDxe%2FMem%2FPool.c;h=5248ee2e6c0221cc2fbd713078b2a4a621c03da0;hp=1adaa1f26970536ae97381617165b5b852112283;hb=d4731a98a3a5ddc2fed73d2998884f2cbee44ba9;hpb=6cea0db87ca8607ac99ad0b76f793dabcf51ac1d
diff --git a/MdeModulePkg/Core/Dxe/Mem/Pool.c b/MdeModulePkg/Core/Dxe/Mem/Pool.c
index 1adaa1f269..5248ee2e6c 100644
--- a/MdeModulePkg/Core/Dxe/Mem/Pool.c
+++ b/MdeModulePkg/Core/Dxe/Mem/Pool.c
@@ -1,21 +1,23 @@
-/** @file
-
+/** @file
UEFI Memory pool management functions.
-Copyright (c) 2006 - 2008, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
-#include
+#include "DxeMain.h"
+#include "Imem.h"
+
+STATIC EFI_LOCK mPoolMemoryLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);
-#define POOL_FREE_SIGNATURE EFI_SIGNATURE_32('p','f','r','0')
+#define POOL_FREE_SIGNATURE SIGNATURE_32('p','f','r','0')
typedef struct {
UINT32 Signature;
UINT32 Index;
@@ -23,36 +25,42 @@ typedef struct {
} POOL_FREE;
-#define POOL_HEAD_SIGNATURE EFI_SIGNATURE_32('p','h','d','0')
+#define POOL_HEAD_SIGNATURE SIGNATURE_32('p','h','d','0')
typedef struct {
UINT32 Signature;
- UINT32 Size;
+ UINT32 Reserved;
EFI_MEMORY_TYPE Type;
- UINTN Reserved;
+ UINTN Size;
CHAR8 Data[1];
} POOL_HEAD;
-#define SIZE_OF_POOL_HEAD EFI_FIELD_OFFSET(POOL_HEAD,Data)
+#define SIZE_OF_POOL_HEAD OFFSET_OF(POOL_HEAD,Data)
-#define POOL_TAIL_SIGNATURE EFI_SIGNATURE_32('p','t','a','l')
+#define POOL_TAIL_SIGNATURE SIGNATURE_32('p','t','a','l')
typedef struct {
UINT32 Signature;
- UINT32 Size;
+ UINT32 Reserved;
+ UINTN Size;
} POOL_TAIL;
-
-#define POOL_SHIFT 7
-
#define POOL_OVERHEAD (SIZE_OF_POOL_HEAD + sizeof(POOL_TAIL))
#define HEAD_TO_TAIL(a) \
((POOL_TAIL *) (((CHAR8 *) (a)) + (a)->Size - sizeof(POOL_TAIL)));
+//
+// Each element is the sum of the 2 previous ones: this allows us to migrate
+// blocks between bins by splitting them up, while not wasting too much memory
+// as we would in a strict power-of-2 sequence
+//
+STATIC CONST UINT16 mPoolSizeTable[] = {
+ 128, 256, 384, 640, 1024, 1664, 2688, 4352, 7040, 11392, 18432, 29824
+};
-#define SIZE_TO_LIST(a) ((a) >> POOL_SHIFT)
-#define LIST_TO_SIZE(a) ((a+1) << POOL_SHIFT)
+#define SIZE_TO_LIST(a) (GetPoolIndexFromSize (a))
+#define LIST_TO_SIZE(a) (mPoolSizeTable [a])
-#define MAX_POOL_LIST SIZE_TO_LIST(DEFAULT_PAGE_ALLOCATION)
+#define MAX_POOL_LIST (ARRAY_SIZE (mPoolSizeTable))
#define MAX_POOL_SIZE (MAX_ADDRESS - POOL_OVERHEAD)
@@ -60,23 +68,48 @@ typedef struct {
// Globals
//
-#define POOL_SIGNATURE EFI_SIGNATURE_32('p','l','s','t')
+#define POOL_SIGNATURE SIGNATURE_32('p','l','s','t')
typedef struct {
INTN Signature;
UINTN Used;
EFI_MEMORY_TYPE MemoryType;
LIST_ENTRY FreeList[MAX_POOL_LIST];
LIST_ENTRY Link;
-} POOL;
-
-
-POOL PoolHead[EfiMaxMemoryType];
-LIST_ENTRY PoolHeadList;
+} POOL;
//
+// Pool header for each memory type.
+//
+POOL mPoolHead[EfiMaxMemoryType];
+
//
+// List of pool header to search for the appropriate memory type.
//
+LIST_ENTRY mPoolHeadList = INITIALIZE_LIST_HEAD_VARIABLE (mPoolHeadList);
+
+/**
+ Get pool size table index from the specified size.
+
+ @param Size The specified size to get index from pool table.
+ @return The index of pool size table.
+
+**/
+STATIC
+UINTN
+GetPoolIndexFromSize (
+ UINTN Size
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < MAX_POOL_LIST; Index++) {
+ if (mPoolSizeTable [Index] >= Size) {
+ return Index;
+ }
+ }
+ return MAX_POOL_LIST;
+}
/**
Called to initialize the pool.
@@ -91,26 +124,24 @@ CoreInitializePool (
UINTN Index;
for (Type=0; Type < EfiMaxMemoryType; Type++) {
- PoolHead[Type].Signature = 0;
- PoolHead[Type].Used = 0;
- PoolHead[Type].MemoryType = (EFI_MEMORY_TYPE) Type;
+ mPoolHead[Type].Signature = 0;
+ mPoolHead[Type].Used = 0;
+ mPoolHead[Type].MemoryType = (EFI_MEMORY_TYPE) Type;
for (Index=0; Index < MAX_POOL_LIST; Index++) {
- InitializeListHead (&PoolHead[Type].FreeList[Index]);
+ InitializeListHead (&mPoolHead[Type].FreeList[Index]);
}
}
- InitializeListHead (&PoolHeadList);
}
/**
Look up pool head for specified memory type.
- @param MemoryType Memory type of which pool head is looked for
+ @param MemoryType Memory type of which pool head is looked for
@return Pointer of Corresponding pool head.
**/
-STATIC
POOL *
LookupPoolHead (
IN EFI_MEMORY_TYPE MemoryType
@@ -120,13 +151,18 @@ LookupPoolHead (
POOL *Pool;
UINTN Index;
- if (MemoryType >= 0 && MemoryType < EfiMaxMemoryType) {
- return &PoolHead[MemoryType];
+ if ((UINT32)MemoryType < EfiMaxMemoryType) {
+ return &mPoolHead[MemoryType];
}
- if (MemoryType < 0) {
+ //
+ // MemoryType values in the range 0x80000000..0xFFFFFFFF are reserved for use by UEFI
+ // OS loaders that are provided by operating system vendors.
+ // MemoryType values in the range 0x70000000..0x7FFFFFFF are reserved for OEM use.
+ //
+ if ((UINT32) MemoryType >= MEMORY_TYPE_OEM_RESERVED_MIN) {
- for (Link = PoolHeadList.ForwardLink; Link != &PoolHeadList; Link = Link->ForwardLink) {
+ for (Link = mPoolHeadList.ForwardLink; Link != &mPoolHeadList; Link = Link->ForwardLink) {
Pool = CR(Link, POOL, Link, POOL_SIGNATURE);
if (Pool->MemoryType == MemoryType) {
return Pool;
@@ -145,7 +181,7 @@ LookupPoolHead (
InitializeListHead (&Pool->FreeList[Index]);
}
- InsertHeadList (&PoolHeadList, &Pool->Link);
+ InsertHeadList (&mPoolHeadList, &Pool->Link);
return Pool;
}
@@ -153,25 +189,26 @@ LookupPoolHead (
return NULL;
}
-
/**
Allocate pool of a particular type.
- @param PoolType Type of pool to allocate
- @param Size The amount of pool to allocate
- @param Buffer The address to return a pointer to the allocated
- pool
+ @param PoolType Type of pool to allocate
+ @param Size The amount of pool to allocate
+ @param Buffer The address to return a pointer to the allocated
+ pool
- @retval EFI_INVALID_PARAMETER PoolType not valid
- @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ PoolType is in the range EfiMaxMemoryType..0x6FFFFFFF.
+ PoolType is EfiPersistentMemory.
+ @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.
@retval EFI_SUCCESS Pool successfully allocated.
**/
EFI_STATUS
EFIAPI
-CoreAllocatePool (
+CoreInternalAllocatePool (
IN EFI_MEMORY_TYPE PoolType,
IN UINTN Size,
OUT VOID **Buffer
@@ -182,13 +219,17 @@ CoreAllocatePool (
//
// If it's not a valid type, fail it
//
- if ((PoolType >= EfiMaxMemoryType && PoolType <= 0x7fffffff) ||
- PoolType == EfiConventionalMemory) {
+ if ((PoolType >= EfiMaxMemoryType && PoolType < MEMORY_TYPE_OEM_RESERVED_MIN) ||
+ (PoolType == EfiConventionalMemory) || (PoolType == EfiPersistentMemory)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Buffer == NULL) {
return EFI_INVALID_PARAMETER;
}
-
+
*Buffer = NULL;
-
+
//
// If size is too large, fail it
// Base on the EFI spec, return status of EFI_OUT_OF_RESOURCES
@@ -200,24 +241,88 @@ CoreAllocatePool (
//
// Acquire the memory lock and make the allocation
//
- Status = CoreAcquireLockOrFail (&gMemoryLock);
+ Status = CoreAcquireLockOrFail (&mPoolMemoryLock);
if (EFI_ERROR (Status)) {
return EFI_OUT_OF_RESOURCES;
}
*Buffer = CoreAllocatePoolI (PoolType, Size);
- CoreReleaseMemoryLock ();
+ CoreReleaseLock (&mPoolMemoryLock);
return (*Buffer != NULL) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES;
}
+/**
+ Allocate pool of a particular type.
+
+ @param PoolType Type of pool to allocate
+ @param Size The amount of pool to allocate
+ @param Buffer The address to return a pointer to the allocated
+ pool
+
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ PoolType is in the range EfiMaxMemoryType..0x6FFFFFFF.
+ PoolType is EfiPersistentMemory.
+ @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.
+ @retval EFI_SUCCESS Pool successfully allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+CoreAllocatePool (
+ IN EFI_MEMORY_TYPE PoolType,
+ IN UINTN Size,
+ OUT VOID **Buffer
+ )
+{
+ EFI_STATUS Status;
+
+ Status = CoreInternalAllocatePool (PoolType, Size, Buffer);
+ if (!EFI_ERROR (Status)) {
+ CoreUpdateProfile (
+ (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0),
+ MemoryProfileActionAllocatePool,
+ PoolType,
+ Size,
+ *Buffer,
+ NULL
+ );
+ InstallMemoryAttributesTableOnMemoryAllocation (PoolType);
+ }
+ return Status;
+}
+
+STATIC
+VOID *
+CoreAllocatePoolPagesI (
+ IN EFI_MEMORY_TYPE PoolType,
+ IN UINTN NoPages,
+ IN UINTN Granularity
+ )
+{
+ VOID *Buffer;
+ EFI_STATUS Status;
+ Status = CoreAcquireLockOrFail (&gMemoryLock);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ Buffer = CoreAllocatePoolPages (PoolType, NoPages, Granularity);
+ CoreReleaseMemoryLock ();
+
+ if (Buffer != NULL) {
+ ApplyMemoryProtectionPolicy (EfiConventionalMemory, PoolType,
+ (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, EFI_PAGES_TO_SIZE (NoPages));
+ }
+ return Buffer;
+}
/**
Internal function to allocate pool of a particular type.
Caller must have the memory lock held
- @param PoolType Type of pool to allocate
- @param Size The amount of pool to allocate
+ @param PoolType Type of pool to allocate
+ @param Size The amount of pool to allocate
@return The allocate pool, or NULL
@@ -236,22 +341,32 @@ CoreAllocatePoolI (
VOID *Buffer;
UINTN Index;
UINTN FSize;
- UINTN Offset;
- UINTN Adjustment;
+ UINTN Offset, MaxOffset;
UINTN NoPages;
+ UINTN Granularity;
+
+ ASSERT_LOCKED (&mPoolMemoryLock);
+
+ if (PoolType == EfiACPIReclaimMemory ||
+ PoolType == EfiACPIMemoryNVS ||
+ PoolType == EfiRuntimeServicesCode ||
+ PoolType == EfiRuntimeServicesData) {
- ASSERT_LOCKED (&gMemoryLock);
+ Granularity = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
+ } else {
+ Granularity = DEFAULT_PAGE_ALLOCATION_GRANULARITY;
+ }
//
// Adjust the size by the pool header & tail overhead
//
-
+
//
// Adjusting the Size to be of proper alignment so that
// we don't get an unaligned access fault later when
// pool_Tail is being initialized
//
- ALIGN_VARIABLE (Size, Adjustment);
+ Size = ALIGN_VARIABLE (Size);
Size += POOL_OVERHEAD;
Index = SIZE_TO_LIST(Size);
@@ -265,10 +380,10 @@ CoreAllocatePoolI (
// If allocation is over max size, just allocate pages for the request
// (slow)
//
- if (Index >= MAX_POOL_LIST) {
- NoPages = EFI_SIZE_TO_PAGES(Size) + EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION) - 1;
- NoPages &= ~(EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION) - 1);
- Head = CoreAllocatePoolPages (PoolType, NoPages, DEFAULT_PAGE_ALLOCATION);
+ if (Index >= SIZE_TO_LIST (Granularity)) {
+ NoPages = EFI_SIZE_TO_PAGES(Size) + EFI_SIZE_TO_PAGES (Granularity) - 1;
+ NoPages &= ~(UINTN)(EFI_SIZE_TO_PAGES (Granularity) - 1);
+ Head = CoreAllocatePoolPagesI (PoolType, NoPages, Granularity);
goto Done;
}
@@ -277,35 +392,56 @@ CoreAllocatePoolI (
//
if (IsListEmpty (&Pool->FreeList[Index])) {
+ Offset = LIST_TO_SIZE (Index);
+ MaxOffset = Granularity;
+
+ //
+ // Check the bins holding larger blocks, and carve one up if needed
+ //
+ while (++Index < SIZE_TO_LIST (Granularity)) {
+ if (!IsListEmpty (&Pool->FreeList[Index])) {
+ Free = CR (Pool->FreeList[Index].ForwardLink, POOL_FREE, Link, POOL_FREE_SIGNATURE);
+ RemoveEntryList (&Free->Link);
+ NewPage = (VOID *) Free;
+ MaxOffset = LIST_TO_SIZE (Index);
+ goto Carve;
+ }
+ }
+
//
// Get another page
//
- NewPage = CoreAllocatePoolPages(PoolType, EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION), DEFAULT_PAGE_ALLOCATION);
+ NewPage = CoreAllocatePoolPagesI (PoolType, EFI_SIZE_TO_PAGES (Granularity), Granularity);
if (NewPage == NULL) {
goto Done;
}
//
- // Carve up new page into free pool blocks
+ // Serve the allocation request from the head of the allocated block
+ //
+Carve:
+ Head = (POOL_HEAD *) NewPage;
+
+ //
+ // Carve up remaining space into free pool blocks
//
- Offset = 0;
- while (Offset < DEFAULT_PAGE_ALLOCATION) {
+ Index--;
+ while (Offset < MaxOffset) {
ASSERT (Index < MAX_POOL_LIST);
FSize = LIST_TO_SIZE(Index);
- while (Offset + FSize <= DEFAULT_PAGE_ALLOCATION) {
- Free = (POOL_FREE *) &NewPage[Offset];
+ while (Offset + FSize <= MaxOffset) {
+ Free = (POOL_FREE *) &NewPage[Offset];
Free->Signature = POOL_FREE_SIGNATURE;
Free->Index = (UINT32)Index;
InsertHeadList (&Pool->FreeList[Index], &Free->Link);
Offset += FSize;
}
-
Index -= 1;
}
- ASSERT (Offset == DEFAULT_PAGE_ALLOCATION);
- Index = SIZE_TO_LIST(Size);
+ ASSERT (Offset == MaxOffset);
+ goto Done;
}
//
@@ -320,27 +456,26 @@ Done:
Buffer = NULL;
if (Head != NULL) {
-
+
//
// If we have a pool buffer, fill in the header & tail info
//
Head->Signature = POOL_HEAD_SIGNATURE;
- Head->Size = (UINT32) Size;
+ Head->Size = Size;
Head->Type = (EFI_MEMORY_TYPE) PoolType;
Tail = HEAD_TO_TAIL (Head);
Tail->Signature = POOL_TAIL_SIGNATURE;
- Tail->Size = (UINT32) Size;
+ Tail->Size = Size;
Buffer = Head->Data;
DEBUG_CLEAR_MEMORY (Buffer, Size - POOL_OVERHEAD);
- DEBUG (
- (DEBUG_POOL,
- "AllocatePoolI: Type %x, Addr %x (len %x) %,d\n",
- PoolType,
- Buffer,
- Size - POOL_OVERHEAD,
- Pool->Used)
- );
+ DEBUG ((
+ DEBUG_POOL,
+ "AllocatePoolI: Type %x, Addr %p (len %lx) %,ld\n", PoolType,
+ Buffer,
+ (UINT64)(Size - POOL_OVERHEAD),
+ (UINT64) Pool->Used
+ ));
//
// Account the allocation
@@ -348,57 +483,107 @@ Done:
Pool->Used += Size;
} else {
- DEBUG ((DEBUG_ERROR | DEBUG_POOL, "AllocatePool: failed to allocate %d bytes\n", Size));
+ DEBUG ((DEBUG_ERROR | DEBUG_POOL, "AllocatePool: failed to allocate %ld bytes\n", (UINT64) Size));
}
return Buffer;
}
-
/**
Frees pool.
- @param Buffer The allocated pool entry to free
+ @param Buffer The allocated pool entry to free
+ @param PoolType Pointer to pool type
- @retval EFI_INVALID_PARAMETER Buffer is not a valid value.
+ @retval EFI_INVALID_PARAMETER Buffer is not a valid value.
@retval EFI_SUCCESS Pool successfully freed.
**/
EFI_STATUS
EFIAPI
-CoreFreePool (
- IN VOID *Buffer
+CoreInternalFreePool (
+ IN VOID *Buffer,
+ OUT EFI_MEMORY_TYPE *PoolType OPTIONAL
)
{
EFI_STATUS Status;
- if (NULL == Buffer) {
+ if (Buffer == NULL) {
return EFI_INVALID_PARAMETER;
}
- CoreAcquireMemoryLock ();
- Status = CoreFreePoolI (Buffer);
- CoreReleaseMemoryLock ();
+ CoreAcquireLock (&mPoolMemoryLock);
+ Status = CoreFreePoolI (Buffer, PoolType);
+ CoreReleaseLock (&mPoolMemoryLock);
+ return Status;
+}
+
+/**
+ Frees pool.
+
+ @param Buffer The allocated pool entry to free
+
+ @retval EFI_INVALID_PARAMETER Buffer is not a valid value.
+ @retval EFI_SUCCESS Pool successfully freed.
+
+**/
+EFI_STATUS
+EFIAPI
+CoreFreePool (
+ IN VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ EFI_MEMORY_TYPE PoolType;
+
+ Status = CoreInternalFreePool (Buffer, &PoolType);
+ if (!EFI_ERROR (Status)) {
+ CoreUpdateProfile (
+ (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0),
+ MemoryProfileActionFreePool,
+ PoolType,
+ 0,
+ Buffer,
+ NULL
+ );
+ InstallMemoryAttributesTableOnMemoryAllocation (PoolType);
+ }
return Status;
}
+STATIC
+VOID
+CoreFreePoolPagesI (
+ IN EFI_MEMORY_TYPE PoolType,
+ IN EFI_PHYSICAL_ADDRESS Memory,
+ IN UINTN NoPages
+ )
+{
+ CoreAcquireMemoryLock ();
+ CoreFreePoolPages (Memory, NoPages);
+ CoreReleaseMemoryLock ();
+ ApplyMemoryProtectionPolicy (PoolType, EfiConventionalMemory,
+ (EFI_PHYSICAL_ADDRESS)(UINTN)Memory, EFI_PAGES_TO_SIZE (NoPages));
+}
/**
Internal function to free a pool entry.
Caller must have the memory lock held
- @param Buffer The allocated pool entry to free
+ @param Buffer The allocated pool entry to free
+ @param PoolType Pointer to pool type
- @retval EFI_INVALID_PARAMETER Buffer not valid
+ @retval EFI_INVALID_PARAMETER Buffer not valid
@retval EFI_SUCCESS Buffer successfully freed.
**/
EFI_STATUS
CoreFreePoolI (
- IN VOID *Buffer
+ IN VOID *Buffer,
+ OUT EFI_MEMORY_TYPE *PoolType OPTIONAL
)
{
POOL *Pool;
@@ -409,30 +594,30 @@ CoreFreePoolI (
UINTN NoPages;
UINTN Size;
CHAR8 *NewPage;
- UINTN FSize;
UINTN Offset;
BOOLEAN AllFree;
+ UINTN Granularity;
- ASSERT(NULL != Buffer);
+ ASSERT(Buffer != NULL);
//
// Get the head & tail of the pool entry
//
Head = CR (Buffer, POOL_HEAD, Data, POOL_HEAD_SIGNATURE);
- ASSERT(NULL != Head);
+ ASSERT(Head != NULL);
if (Head->Signature != POOL_HEAD_SIGNATURE) {
return EFI_INVALID_PARAMETER;
}
Tail = HEAD_TO_TAIL (Head);
- ASSERT(NULL != Tail);
+ ASSERT(Tail != NULL);
//
// Debug
//
ASSERT (Tail->Signature == POOL_TAIL_SIGNATURE);
ASSERT (Head->Size == Tail->Size);
- ASSERT_LOCKED (&gMemoryLock);
+ ASSERT_LOCKED (&mPoolMemoryLock);
if (Tail->Signature != POOL_TAIL_SIGNATURE) {
return EFI_INVALID_PARAMETER;
@@ -451,10 +636,24 @@ CoreFreePoolI (
return EFI_INVALID_PARAMETER;
}
Pool->Used -= Size;
- DEBUG ((DEBUG_POOL, "FreePool: %x (len %x) %,d\n", Head->Data, Head->Size - POOL_OVERHEAD, Pool->Used));
+ DEBUG ((DEBUG_POOL, "FreePool: %p (len %lx) %,ld\n", Head->Data, (UINT64)(Head->Size - POOL_OVERHEAD), (UINT64) Pool->Used));
+
+ if (Head->Type == EfiACPIReclaimMemory ||
+ Head->Type == EfiACPIMemoryNVS ||
+ Head->Type == EfiRuntimeServicesCode ||
+ Head->Type == EfiRuntimeServicesData) {
+
+ Granularity = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
+ } else {
+ Granularity = DEFAULT_PAGE_ALLOCATION_GRANULARITY;
+ }
+
+ if (PoolType != NULL) {
+ *PoolType = Head->Type;
+ }
//
- // Determine the pool list
+ // Determine the pool list
//
Index = SIZE_TO_LIST(Size);
DEBUG_CLEAR_MEMORY (Head, Size);
@@ -462,14 +661,14 @@ CoreFreePoolI (
//
// If it's not on the list, it must be pool pages
//
- if (Index >= MAX_POOL_LIST) {
+ if (Index >= SIZE_TO_LIST (Granularity)) {
//
// Return the memory pages back to free memory
//
- NoPages = EFI_SIZE_TO_PAGES(Size) + EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION) - 1;
- NoPages &= ~(EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION) - 1);
- CoreFreePoolPages ((EFI_PHYSICAL_ADDRESS) (UINTN) Head, NoPages);
+ NoPages = EFI_SIZE_TO_PAGES(Size) + EFI_SIZE_TO_PAGES (Granularity) - 1;
+ NoPages &= ~(UINTN)(EFI_SIZE_TO_PAGES (Granularity) - 1);
+ CoreFreePoolPagesI (Pool->MemoryType, (EFI_PHYSICAL_ADDRESS) (UINTN) Head, NoPages);
} else {
@@ -477,79 +676,70 @@ CoreFreePoolI (
// Put the pool entry onto the free pool list
//
Free = (POOL_FREE *) Head;
- ASSERT(NULL != Free);
+ ASSERT(Free != NULL);
Free->Signature = POOL_FREE_SIGNATURE;
Free->Index = (UINT32)Index;
InsertHeadList (&Pool->FreeList[Index], &Free->Link);
//
- // See if all the pool entries in the same page as Free are freed pool
+ // See if all the pool entries in the same page as Free are freed pool
// entries
//
- NewPage = (CHAR8 *)((UINTN)Free & ~((DEFAULT_PAGE_ALLOCATION) -1));
+ NewPage = (CHAR8 *)((UINTN)Free & ~(Granularity - 1));
Free = (POOL_FREE *) &NewPage[0];
- ASSERT(NULL != Free);
+ ASSERT(Free != NULL);
if (Free->Signature == POOL_FREE_SIGNATURE) {
- Index = Free->Index;
-
AllFree = TRUE;
Offset = 0;
-
- while ((Offset < DEFAULT_PAGE_ALLOCATION) && (AllFree)) {
- FSize = LIST_TO_SIZE(Index);
- while (Offset + FSize <= DEFAULT_PAGE_ALLOCATION) {
- Free = (POOL_FREE *) &NewPage[Offset];
- ASSERT(NULL != Free);
- if (Free->Signature != POOL_FREE_SIGNATURE) {
- AllFree = FALSE;
- }
- Offset += FSize;
+
+ while ((Offset < Granularity) && (AllFree)) {
+ Free = (POOL_FREE *) &NewPage[Offset];
+ ASSERT(Free != NULL);
+ if (Free->Signature != POOL_FREE_SIGNATURE) {
+ AllFree = FALSE;
}
- Index -= 1;
+ Offset += LIST_TO_SIZE(Free->Index);
}
if (AllFree) {
//
- // All of the pool entries in the same page as Free are free pool
+ // All of the pool entries in the same page as Free are free pool
// entries
// Remove all of these pool entries from the free loop lists.
//
Free = (POOL_FREE *) &NewPage[0];
- ASSERT(NULL != Free);
- Index = Free->Index;
+ ASSERT(Free != NULL);
Offset = 0;
-
- while (Offset < DEFAULT_PAGE_ALLOCATION) {
- FSize = LIST_TO_SIZE(Index);
- while (Offset + FSize <= DEFAULT_PAGE_ALLOCATION) {
- Free = (POOL_FREE *) &NewPage[Offset];
- ASSERT(NULL != Free);
- RemoveEntryList (&Free->Link);
- Offset += FSize;
- }
- Index -= 1;
+
+ while (Offset < Granularity) {
+ Free = (POOL_FREE *) &NewPage[Offset];
+ ASSERT(Free != NULL);
+ RemoveEntryList (&Free->Link);
+ Offset += LIST_TO_SIZE(Free->Index);
}
//
// Free the page
//
- CoreFreePoolPages ((EFI_PHYSICAL_ADDRESS) (UINTN)NewPage, EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION));
+ CoreFreePoolPagesI (Pool->MemoryType, (EFI_PHYSICAL_ADDRESS) (UINTN)NewPage,
+ EFI_SIZE_TO_PAGES (Granularity));
}
}
}
//
- // If this is an OS specific memory type, then check to see if the last
+ // If this is an OS/OEM specific memory type, then check to see if the last
// portion of that memory type has been freed. If it has, then free the
// list entry for that memory type
//
- if (Pool->MemoryType < 0 && Pool->Used == 0) {
+ if (((UINT32) Pool->MemoryType >= MEMORY_TYPE_OEM_RESERVED_MIN) && Pool->Used == 0) {
RemoveEntryList (&Pool->Link);
- CoreFreePoolI (Pool);
+ CoreFreePoolI (Pool, NULL);
}
return EFI_SUCCESS;
}
+