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