]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Mem/Pool.c
MdeModulePkg DxeCore: Fix a memory leak in InstallMemoryAttributesTable()
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Mem / Pool.c
CommitLineData
23c98c94 1/** @file\r
504214c4
LG
2 UEFI Memory pool management functions.\r
3\r
09159a29 4Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>\r
cd5ebaa0 5This program and the accompanying materials\r
23c98c94 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
28a00297 12\r
504214c4 13**/\r
28a00297 14\r
9c4ac31c 15#include "DxeMain.h"\r
ec90508b 16#include "Imem.h"\r
28a00297 17\r
f3f2e05d 18#define POOL_FREE_SIGNATURE SIGNATURE_32('p','f','r','0')\r
28a00297 19typedef struct {\r
20 UINT32 Signature;\r
21 UINT32 Index;\r
22 LIST_ENTRY Link;\r
23} POOL_FREE;\r
24\r
25\r
f3f2e05d 26#define POOL_HEAD_SIGNATURE SIGNATURE_32('p','h','d','0')\r
28a00297 27typedef struct {\r
28 UINT32 Signature;\r
bb683bf4 29 UINT32 Reserved;\r
28a00297 30 EFI_MEMORY_TYPE Type;\r
bb683bf4 31 UINTN Size;\r
28a00297 32 CHAR8 Data[1];\r
33} POOL_HEAD;\r
34\r
f3f2e05d 35#define SIZE_OF_POOL_HEAD OFFSET_OF(POOL_HEAD,Data)\r
28a00297 36\r
f3f2e05d 37#define POOL_TAIL_SIGNATURE SIGNATURE_32('p','t','a','l')\r
28a00297 38typedef struct {\r
39 UINT32 Signature;\r
bb683bf4
SZ
40 UINT32 Reserved;\r
41 UINTN Size;\r
28a00297 42} POOL_TAIL;\r
43\r
28a00297 44#define POOL_OVERHEAD (SIZE_OF_POOL_HEAD + sizeof(POOL_TAIL))\r
45\r
46#define HEAD_TO_TAIL(a) \\r
47 ((POOL_TAIL *) (((CHAR8 *) (a)) + (a)->Size - sizeof(POOL_TAIL)));\r
48\r
f2c7daf6
AB
49//\r
50// Each element is the sum of the 2 previous ones: this allows us to migrate\r
51// blocks between bins by splitting them up, while not wasting too much memory\r
52// as we would in a strict power-of-2 sequence\r
53//\r
54STATIC CONST UINT16 mPoolSizeTable[] = {\r
55 64, 128, 192, 320, 512, 832, 1344, 2176, 3520, 5696, 9216, 14912, 24128\r
56};\r
28a00297 57\r
f2c7daf6
AB
58#define SIZE_TO_LIST(a) (GetPoolIndexFromSize (a))\r
59#define LIST_TO_SIZE(a) (mPoolSizeTable [a])\r
28a00297 60\r
f2c7daf6 61#define MAX_POOL_LIST (sizeof (mPoolSizeTable) / sizeof (mPoolSizeTable[0]))\r
28a00297 62\r
63#define MAX_POOL_SIZE (MAX_ADDRESS - POOL_OVERHEAD)\r
64\r
65//\r
66// Globals\r
67//\r
68\r
f3f2e05d 69#define POOL_SIGNATURE SIGNATURE_32('p','l','s','t')\r
28a00297 70typedef struct {\r
71 INTN Signature;\r
72 UINTN Used;\r
73 EFI_MEMORY_TYPE MemoryType;\r
74 LIST_ENTRY FreeList[MAX_POOL_LIST];\r
75 LIST_ENTRY Link;\r
022c6d45 76} POOL;\r
28a00297 77\r
28a00297 78//\r
e94a9ff7 79// Pool header for each memory type.\r
80//\r
81POOL mPoolHead[EfiMaxMemoryType];\r
82\r
28a00297 83//\r
e94a9ff7 84// List of pool header to search for the appropriate memory type.\r
28a00297 85//\r
57b4ecb9 86LIST_ENTRY mPoolHeadList = INITIALIZE_LIST_HEAD_VARIABLE (mPoolHeadList);\r
28a00297 87\r
dd51e45b
SQ
88/**\r
89 Get pool size table index from the specified size.\r
90\r
91 @param Size The specified size to get index from pool table.\r
92\r
93 @return The index of pool size table.\r
94\r
95**/\r
f2c7daf6
AB
96STATIC\r
97UINTN\r
98GetPoolIndexFromSize (\r
99 UINTN Size\r
100 )\r
101{\r
102 UINTN Index;\r
103\r
104 for (Index = 0; Index < MAX_POOL_LIST; Index++) {\r
105 if (mPoolSizeTable [Index] >= Size) {\r
106 return Index;\r
107 }\r
108 }\r
109 return MAX_POOL_LIST;\r
110}\r
162ed594 111\r
112/**\r
113 Called to initialize the pool.\r
114\r
115**/\r
28a00297 116VOID\r
117CoreInitializePool (\r
118 VOID\r
119 )\r
28a00297 120{\r
121 UINTN Type;\r
122 UINTN Index;\r
123\r
124 for (Type=0; Type < EfiMaxMemoryType; Type++) {\r
e94a9ff7 125 mPoolHead[Type].Signature = 0;\r
126 mPoolHead[Type].Used = 0;\r
127 mPoolHead[Type].MemoryType = (EFI_MEMORY_TYPE) Type;\r
28a00297 128 for (Index=0; Index < MAX_POOL_LIST; Index++) {\r
bb683bf4 129 InitializeListHead (&mPoolHead[Type].FreeList[Index]);\r
28a00297 130 }\r
131 }\r
28a00297 132}\r
133\r
28a00297 134\r
162ed594 135/**\r
28a00297 136 Look up pool head for specified memory type.\r
137\r
022c6d45 138 @param MemoryType Memory type of which pool head is looked for\r
28a00297 139\r
162ed594 140 @return Pointer of Corresponding pool head.\r
28a00297 141\r
162ed594 142**/\r
162ed594 143POOL *\r
144LookupPoolHead (\r
145 IN EFI_MEMORY_TYPE MemoryType\r
146 )\r
28a00297 147{\r
148 LIST_ENTRY *Link;\r
149 POOL *Pool;\r
150 UINTN Index;\r
151\r
3d78c020 152 if ((UINT32)MemoryType < EfiMaxMemoryType) {\r
e94a9ff7 153 return &mPoolHead[MemoryType];\r
28a00297 154 }\r
155\r
dc8d93ca 156 //\r
8ee25f48
SZ
157 // MemoryType values in the range 0x80000000..0xFFFFFFFF are reserved for use by UEFI\r
158 // OS loaders that are provided by operating system vendors.\r
159 // MemoryType values in the range 0x70000000..0x7FFFFFFF are reserved for OEM use.\r
dc8d93ca 160 //\r
8ee25f48 161 if ((UINT32) MemoryType >= MEMORY_TYPE_OEM_RESERVED_MIN) {\r
28a00297 162\r
e94a9ff7 163 for (Link = mPoolHeadList.ForwardLink; Link != &mPoolHeadList; Link = Link->ForwardLink) {\r
28a00297 164 Pool = CR(Link, POOL, Link, POOL_SIGNATURE);\r
165 if (Pool->MemoryType == MemoryType) {\r
166 return Pool;\r
167 }\r
168 }\r
169\r
170 Pool = CoreAllocatePoolI (EfiBootServicesData, sizeof (POOL));\r
171 if (Pool == NULL) {\r
172 return NULL;\r
173 }\r
174\r
175 Pool->Signature = POOL_SIGNATURE;\r
176 Pool->Used = 0;\r
177 Pool->MemoryType = MemoryType;\r
178 for (Index=0; Index < MAX_POOL_LIST; Index++) {\r
179 InitializeListHead (&Pool->FreeList[Index]);\r
180 }\r
181\r
e94a9ff7 182 InsertHeadList (&mPoolHeadList, &Pool->Link);\r
28a00297 183\r
184 return Pool;\r
185 }\r
186\r
187 return NULL;\r
188}\r
189\r
022c6d45 190\r
28a00297 191\r
162ed594 192/**\r
193 Allocate pool of a particular type.\r
194\r
022c6d45 195 @param PoolType Type of pool to allocate\r
196 @param Size The amount of pool to allocate\r
197 @param Buffer The address to return a pointer to the allocated\r
198 pool\r
162ed594 199\r
2eb989bc
SZ
200 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
201 PoolType is in the range EfiMaxMemoryType..0x6FFFFFFF.\r
202 PoolType is EfiPersistentMemory.\r
022c6d45 203 @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.\r
162ed594 204 @retval EFI_SUCCESS Pool successfully allocated.\r
205\r
206**/\r
28a00297 207EFI_STATUS\r
208EFIAPI\r
84edd20b 209CoreInternalAllocatePool (\r
28a00297 210 IN EFI_MEMORY_TYPE PoolType,\r
211 IN UINTN Size,\r
212 OUT VOID **Buffer\r
213 )\r
28a00297 214{\r
215 EFI_STATUS Status;\r
216\r
217 //\r
218 // If it's not a valid type, fail it\r
219 //\r
8ee25f48 220 if ((PoolType >= EfiMaxMemoryType && PoolType < MEMORY_TYPE_OEM_RESERVED_MIN) ||\r
a671a012 221 (PoolType == EfiConventionalMemory) || (PoolType == EfiPersistentMemory)) {\r
28a00297 222 return EFI_INVALID_PARAMETER;\r
223 }\r
022c6d45 224\r
3e058701
ED
225 if (Buffer == NULL) {\r
226 return EFI_INVALID_PARAMETER;\r
227 }\r
228\r
28a00297 229 *Buffer = NULL;\r
022c6d45 230\r
28a00297 231 //\r
232 // If size is too large, fail it\r
233 // Base on the EFI spec, return status of EFI_OUT_OF_RESOURCES\r
234 //\r
235 if (Size > MAX_POOL_SIZE) {\r
236 return EFI_OUT_OF_RESOURCES;\r
237 }\r
238\r
239 //\r
240 // Acquire the memory lock and make the allocation\r
241 //\r
242 Status = CoreAcquireLockOrFail (&gMemoryLock);\r
243 if (EFI_ERROR (Status)) {\r
244 return EFI_OUT_OF_RESOURCES;\r
245 }\r
246\r
247 *Buffer = CoreAllocatePoolI (PoolType, Size);\r
248 CoreReleaseMemoryLock ();\r
249 return (*Buffer != NULL) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES;\r
250}\r
251\r
84edd20b
SZ
252/**\r
253 Allocate pool of a particular type.\r
254\r
255 @param PoolType Type of pool to allocate\r
256 @param Size The amount of pool to allocate\r
257 @param Buffer The address to return a pointer to the allocated\r
258 pool\r
259\r
2eb989bc
SZ
260 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
261 PoolType is in the range EfiMaxMemoryType..0x6FFFFFFF.\r
262 PoolType is EfiPersistentMemory.\r
84edd20b
SZ
263 @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.\r
264 @retval EFI_SUCCESS Pool successfully allocated.\r
265\r
266**/\r
267EFI_STATUS\r
268EFIAPI\r
269CoreAllocatePool (\r
270 IN EFI_MEMORY_TYPE PoolType,\r
271 IN UINTN Size,\r
272 OUT VOID **Buffer\r
273 )\r
274{\r
275 EFI_STATUS Status;\r
28a00297 276\r
84edd20b
SZ
277 Status = CoreInternalAllocatePool (PoolType, Size, Buffer);\r
278 if (!EFI_ERROR (Status)) {\r
279 CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionAllocatePool, PoolType, Size, *Buffer);\r
280 }\r
281 return Status;\r
282}\r
28a00297 283\r
162ed594 284/**\r
28a00297 285 Internal function to allocate pool of a particular type.\r
28a00297 286 Caller must have the memory lock held\r
287\r
022c6d45 288 @param PoolType Type of pool to allocate\r
289 @param Size The amount of pool to allocate\r
28a00297 290\r
162ed594 291 @return The allocate pool, or NULL\r
28a00297 292\r
162ed594 293**/\r
294VOID *\r
295CoreAllocatePoolI (\r
296 IN EFI_MEMORY_TYPE PoolType,\r
297 IN UINTN Size\r
298 )\r
28a00297 299{\r
300 POOL *Pool;\r
301 POOL_FREE *Free;\r
302 POOL_HEAD *Head;\r
303 POOL_TAIL *Tail;\r
304 CHAR8 *NewPage;\r
305 VOID *Buffer;\r
306 UINTN Index;\r
307 UINTN FSize;\r
6860b92c 308 UINTN Offset, MaxOffset;\r
28a00297 309 UINTN NoPages;\r
7970100c 310 UINTN Granularity;\r
28a00297 311\r
312 ASSERT_LOCKED (&gMemoryLock);\r
313\r
7970100c
AB
314 if (PoolType == EfiACPIReclaimMemory ||\r
315 PoolType == EfiACPIMemoryNVS ||\r
316 PoolType == EfiRuntimeServicesCode ||\r
317 PoolType == EfiRuntimeServicesData) {\r
318\r
319 Granularity = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT;\r
320 } else {\r
321 Granularity = DEFAULT_PAGE_ALLOCATION;\r
322 }\r
323\r
28a00297 324 //\r
325 // Adjust the size by the pool header & tail overhead\r
326 //\r
022c6d45 327\r
28a00297 328 //\r
329 // Adjusting the Size to be of proper alignment so that\r
330 // we don't get an unaligned access fault later when\r
331 // pool_Tail is being initialized\r
332 //\r
f0d5cbb6 333 Size = ALIGN_VARIABLE (Size);\r
28a00297 334\r
335 Size += POOL_OVERHEAD;\r
336 Index = SIZE_TO_LIST(Size);\r
337 Pool = LookupPoolHead (PoolType);\r
338 if (Pool== NULL) {\r
339 return NULL;\r
340 }\r
341 Head = NULL;\r
342\r
343 //\r
344 // If allocation is over max size, just allocate pages for the request\r
345 // (slow)\r
346 //\r
f2c7daf6 347 if (Index >= SIZE_TO_LIST (Granularity)) {\r
7970100c
AB
348 NoPages = EFI_SIZE_TO_PAGES(Size) + EFI_SIZE_TO_PAGES (Granularity) - 1;\r
349 NoPages &= ~(UINTN)(EFI_SIZE_TO_PAGES (Granularity) - 1);\r
350 Head = CoreAllocatePoolPages (PoolType, NoPages, Granularity);\r
28a00297 351 goto Done;\r
352 }\r
353\r
354 //\r
355 // If there's no free pool in the proper list size, go get some more pages\r
356 //\r
357 if (IsListEmpty (&Pool->FreeList[Index])) {\r
358\r
6860b92c
AB
359 Offset = LIST_TO_SIZE (Index);\r
360 MaxOffset = Granularity;\r
361\r
362 //\r
363 // Check the bins holding larger blocks, and carve one up if needed\r
364 //\r
365 while (++Index < SIZE_TO_LIST (Granularity)) {\r
366 if (!IsListEmpty (&Pool->FreeList[Index])) {\r
367 Free = CR (Pool->FreeList[Index].ForwardLink, POOL_FREE, Link, POOL_FREE_SIGNATURE);\r
368 RemoveEntryList (&Free->Link);\r
369 NewPage = (VOID *) Free;\r
370 MaxOffset = LIST_TO_SIZE (Index);\r
371 goto Carve;\r
372 }\r
373 }\r
374\r
28a00297 375 //\r
376 // Get another page\r
377 //\r
7970100c 378 NewPage = CoreAllocatePoolPages(PoolType, EFI_SIZE_TO_PAGES (Granularity), Granularity);\r
28a00297 379 if (NewPage == NULL) {\r
380 goto Done;\r
381 }\r
382\r
383 //\r
f8aabf6e 384 // Serve the allocation request from the head of the allocated block\r
28a00297 385 //\r
6860b92c 386Carve:\r
f8aabf6e 387 Head = (POOL_HEAD *) NewPage;\r
f8aabf6e
AB
388\r
389 //\r
390 // Carve up remaining space into free pool blocks\r
391 //\r
6860b92c
AB
392 Index--;\r
393 while (Offset < MaxOffset) {\r
28a00297 394 ASSERT (Index < MAX_POOL_LIST);\r
395 FSize = LIST_TO_SIZE(Index);\r
396\r
6860b92c 397 while (Offset + FSize <= MaxOffset) {\r
022c6d45 398 Free = (POOL_FREE *) &NewPage[Offset];\r
28a00297 399 Free->Signature = POOL_FREE_SIGNATURE;\r
400 Free->Index = (UINT32)Index;\r
401 InsertHeadList (&Pool->FreeList[Index], &Free->Link);\r
162ed594 402 Offset += FSize;\r
28a00297 403 }\r
28a00297 404 Index -= 1;\r
405 }\r
406\r
6860b92c 407 ASSERT (Offset == MaxOffset);\r
f8aabf6e 408 goto Done;\r
28a00297 409 }\r
410\r
411 //\r
412 // Remove entry from free pool list\r
413 //\r
414 Free = CR (Pool->FreeList[Index].ForwardLink, POOL_FREE, Link, POOL_FREE_SIGNATURE);\r
415 RemoveEntryList (&Free->Link);\r
416\r
417 Head = (POOL_HEAD *) Free;\r
418\r
419Done:\r
420 Buffer = NULL;\r
421\r
422 if (Head != NULL) {\r
022c6d45 423\r
28a00297 424 //\r
425 // If we have a pool buffer, fill in the header & tail info\r
426 //\r
427 Head->Signature = POOL_HEAD_SIGNATURE;\r
bb683bf4 428 Head->Size = Size;\r
28a00297 429 Head->Type = (EFI_MEMORY_TYPE) PoolType;\r
430 Tail = HEAD_TO_TAIL (Head);\r
431 Tail->Signature = POOL_TAIL_SIGNATURE;\r
bb683bf4 432 Tail->Size = Size;\r
28a00297 433 Buffer = Head->Data;\r
434 DEBUG_CLEAR_MEMORY (Buffer, Size - POOL_OVERHEAD);\r
435\r
e94a9ff7 436 DEBUG ((\r
437 DEBUG_POOL,\r
57b4ecb9 438 "AllocatePoolI: Type %x, Addr %p (len %lx) %,ld\n", PoolType,\r
022c6d45 439 Buffer,\r
57b4ecb9 440 (UINT64)(Size - POOL_OVERHEAD),\r
441 (UINT64) Pool->Used\r
e94a9ff7 442 ));\r
28a00297 443\r
444 //\r
445 // Account the allocation\r
446 //\r
447 Pool->Used += Size;\r
448\r
449 } else {\r
57b4ecb9 450 DEBUG ((DEBUG_ERROR | DEBUG_POOL, "AllocatePool: failed to allocate %ld bytes\n", (UINT64) Size));\r
28a00297 451 }\r
452\r
453 return Buffer;\r
454}\r
022c6d45 455\r
28a00297 456\r
457\r
162ed594 458/**\r
28a00297 459 Frees pool.\r
460\r
022c6d45 461 @param Buffer The allocated pool entry to free\r
28a00297 462\r
022c6d45 463 @retval EFI_INVALID_PARAMETER Buffer is not a valid value.\r
162ed594 464 @retval EFI_SUCCESS Pool successfully freed.\r
28a00297 465\r
162ed594 466**/\r
467EFI_STATUS\r
468EFIAPI\r
84edd20b 469CoreInternalFreePool (\r
162ed594 470 IN VOID *Buffer\r
471 )\r
28a00297 472{\r
473 EFI_STATUS Status;\r
474\r
e94a9ff7 475 if (Buffer == NULL) {\r
28a00297 476 return EFI_INVALID_PARAMETER;\r
477 }\r
478\r
479 CoreAcquireMemoryLock ();\r
480 Status = CoreFreePoolI (Buffer);\r
481 CoreReleaseMemoryLock ();\r
482 return Status;\r
483}\r
484\r
84edd20b
SZ
485/**\r
486 Frees pool.\r
487\r
488 @param Buffer The allocated pool entry to free\r
489\r
490 @retval EFI_INVALID_PARAMETER Buffer is not a valid value.\r
491 @retval EFI_SUCCESS Pool successfully freed.\r
492\r
493**/\r
494EFI_STATUS\r
495EFIAPI\r
496CoreFreePool (\r
497 IN VOID *Buffer\r
498 )\r
499{\r
500 EFI_STATUS Status;\r
736a692e
HT
501\r
502 Status = CoreInternalFreePool (Buffer);\r
503 if (!EFI_ERROR (Status)) {\r
504 CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionFreePool, (EFI_MEMORY_TYPE) 0, 0, Buffer);\r
505 }\r
506 return Status;\r
507}\r
28a00297 508\r
162ed594 509/**\r
28a00297 510 Internal function to free a pool entry.\r
28a00297 511 Caller must have the memory lock held\r
512\r
022c6d45 513 @param Buffer The allocated pool entry to free\r
28a00297 514\r
022c6d45 515 @retval EFI_INVALID_PARAMETER Buffer not valid\r
162ed594 516 @retval EFI_SUCCESS Buffer successfully freed.\r
28a00297 517\r
162ed594 518**/\r
519EFI_STATUS\r
520CoreFreePoolI (\r
521 IN VOID *Buffer\r
522 )\r
28a00297 523{\r
524 POOL *Pool;\r
525 POOL_HEAD *Head;\r
526 POOL_TAIL *Tail;\r
527 POOL_FREE *Free;\r
528 UINTN Index;\r
529 UINTN NoPages;\r
530 UINTN Size;\r
531 CHAR8 *NewPage;\r
162ed594 532 UINTN Offset;\r
28a00297 533 BOOLEAN AllFree;\r
7970100c 534 UINTN Granularity;\r
28a00297 535\r
57b4ecb9 536 ASSERT(Buffer != NULL);\r
28a00297 537 //\r
538 // Get the head & tail of the pool entry\r
539 //\r
540 Head = CR (Buffer, POOL_HEAD, Data, POOL_HEAD_SIGNATURE);\r
57b4ecb9 541 ASSERT(Head != NULL);\r
28a00297 542\r
543 if (Head->Signature != POOL_HEAD_SIGNATURE) {\r
544 return EFI_INVALID_PARAMETER;\r
545 }\r
546\r
547 Tail = HEAD_TO_TAIL (Head);\r
57b4ecb9 548 ASSERT(Tail != NULL);\r
28a00297 549\r
550 //\r
551 // Debug\r
552 //\r
553 ASSERT (Tail->Signature == POOL_TAIL_SIGNATURE);\r
554 ASSERT (Head->Size == Tail->Size);\r
555 ASSERT_LOCKED (&gMemoryLock);\r
556\r
557 if (Tail->Signature != POOL_TAIL_SIGNATURE) {\r
558 return EFI_INVALID_PARAMETER;\r
559 }\r
560\r
561 if (Head->Size != Tail->Size) {\r
562 return EFI_INVALID_PARAMETER;\r
563 }\r
564\r
565 //\r
566 // Determine the pool type and account for it\r
567 //\r
568 Size = Head->Size;\r
569 Pool = LookupPoolHead (Head->Type);\r
570 if (Pool == NULL) {\r
571 return EFI_INVALID_PARAMETER;\r
572 }\r
573 Pool->Used -= Size;\r
57b4ecb9 574 DEBUG ((DEBUG_POOL, "FreePool: %p (len %lx) %,ld\n", Head->Data, (UINT64)(Head->Size - POOL_OVERHEAD), (UINT64) Pool->Used));\r
28a00297 575\r
7970100c
AB
576 if (Head->Type == EfiACPIReclaimMemory ||\r
577 Head->Type == EfiACPIMemoryNVS ||\r
578 Head->Type == EfiRuntimeServicesCode ||\r
579 Head->Type == EfiRuntimeServicesData) {\r
580\r
581 Granularity = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT;\r
582 } else {\r
583 Granularity = DEFAULT_PAGE_ALLOCATION;\r
584 }\r
585\r
28a00297 586 //\r
022c6d45 587 // Determine the pool list\r
28a00297 588 //\r
589 Index = SIZE_TO_LIST(Size);\r
590 DEBUG_CLEAR_MEMORY (Head, Size);\r
591\r
592 //\r
593 // If it's not on the list, it must be pool pages\r
594 //\r
f2c7daf6 595 if (Index >= SIZE_TO_LIST (Granularity)) {\r
28a00297 596\r
597 //\r
598 // Return the memory pages back to free memory\r
599 //\r
7970100c
AB
600 NoPages = EFI_SIZE_TO_PAGES(Size) + EFI_SIZE_TO_PAGES (Granularity) - 1;\r
601 NoPages &= ~(UINTN)(EFI_SIZE_TO_PAGES (Granularity) - 1);\r
28a00297 602 CoreFreePoolPages ((EFI_PHYSICAL_ADDRESS) (UINTN) Head, NoPages);\r
603\r
604 } else {\r
605\r
606 //\r
607 // Put the pool entry onto the free pool list\r
608 //\r
609 Free = (POOL_FREE *) Head;\r
57b4ecb9 610 ASSERT(Free != NULL);\r
28a00297 611 Free->Signature = POOL_FREE_SIGNATURE;\r
612 Free->Index = (UINT32)Index;\r
613 InsertHeadList (&Pool->FreeList[Index], &Free->Link);\r
614\r
615 //\r
022c6d45 616 // See if all the pool entries in the same page as Free are freed pool\r
28a00297 617 // entries\r
618 //\r
7970100c 619 NewPage = (CHAR8 *)((UINTN)Free & ~(Granularity - 1));\r
28a00297 620 Free = (POOL_FREE *) &NewPage[0];\r
e94a9ff7 621 ASSERT(Free != NULL);\r
28a00297 622\r
623 if (Free->Signature == POOL_FREE_SIGNATURE) {\r
624\r
28a00297 625 AllFree = TRUE;\r
162ed594 626 Offset = 0;\r
022c6d45 627\r
7970100c 628 while ((Offset < Granularity) && (AllFree)) {\r
7e8e2205
AB
629 Free = (POOL_FREE *) &NewPage[Offset];\r
630 ASSERT(Free != NULL);\r
631 if (Free->Signature != POOL_FREE_SIGNATURE) {\r
632 AllFree = FALSE;\r
28a00297 633 }\r
7e8e2205 634 Offset += LIST_TO_SIZE(Free->Index);\r
28a00297 635 }\r
636\r
637 if (AllFree) {\r
638\r
639 //\r
022c6d45 640 // All of the pool entries in the same page as Free are free pool\r
28a00297 641 // entries\r
642 // Remove all of these pool entries from the free loop lists.\r
643 //\r
644 Free = (POOL_FREE *) &NewPage[0];\r
57b4ecb9 645 ASSERT(Free != NULL);\r
162ed594 646 Offset = 0;\r
022c6d45 647\r
7970100c 648 while (Offset < Granularity) {\r
7e8e2205
AB
649 Free = (POOL_FREE *) &NewPage[Offset];\r
650 ASSERT(Free != NULL);\r
651 RemoveEntryList (&Free->Link);\r
652 Offset += LIST_TO_SIZE(Free->Index);\r
28a00297 653 }\r
654\r
655 //\r
656 // Free the page\r
657 //\r
7970100c 658 CoreFreePoolPages ((EFI_PHYSICAL_ADDRESS) (UINTN)NewPage, EFI_SIZE_TO_PAGES (Granularity));\r
28a00297 659 }\r
660 }\r
661 }\r
662\r
663 //\r
09159a29 664 // If this is an OS/OEM specific memory type, then check to see if the last\r
28a00297 665 // portion of that memory type has been freed. If it has, then free the\r
666 // list entry for that memory type\r
667 //\r
09159a29 668 if (((UINT32) Pool->MemoryType >= MEMORY_TYPE_OEM_RESERVED_MIN) && Pool->Used == 0) {\r
28a00297 669 RemoveEntryList (&Pool->Link);\r
670 CoreFreePoolI (Pool);\r
671 }\r
672\r
673 return EFI_SUCCESS;\r
674}\r
84edd20b 675\r