]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Mem/Pool.c
MdePkg: Convert non DOS format files to DOS format
[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
277\r
278 ASSERT_LOCKED (&gMemoryLock);\r
279\r
280 //\r
281 // Adjust the size by the pool header & tail overhead\r
282 //\r
022c6d45 283\r
28a00297 284 //\r
285 // Adjusting the Size to be of proper alignment so that\r
286 // we don't get an unaligned access fault later when\r
287 // pool_Tail is being initialized\r
288 //\r
f0d5cbb6 289 Size = ALIGN_VARIABLE (Size);\r
28a00297 290\r
291 Size += POOL_OVERHEAD;\r
292 Index = SIZE_TO_LIST(Size);\r
293 Pool = LookupPoolHead (PoolType);\r
294 if (Pool== NULL) {\r
295 return NULL;\r
296 }\r
297 Head = NULL;\r
298\r
299 //\r
300 // If allocation is over max size, just allocate pages for the request\r
301 // (slow)\r
302 //\r
303 if (Index >= MAX_POOL_LIST) {\r
304 NoPages = EFI_SIZE_TO_PAGES(Size) + EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION) - 1;\r
6e1e5405 305 NoPages &= ~(UINTN)(EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION) - 1);\r
28a00297 306 Head = CoreAllocatePoolPages (PoolType, NoPages, DEFAULT_PAGE_ALLOCATION);\r
307 goto Done;\r
308 }\r
309\r
310 //\r
311 // If there's no free pool in the proper list size, go get some more pages\r
312 //\r
313 if (IsListEmpty (&Pool->FreeList[Index])) {\r
314\r
315 //\r
316 // Get another page\r
317 //\r
318 NewPage = CoreAllocatePoolPages(PoolType, EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION), DEFAULT_PAGE_ALLOCATION);\r
319 if (NewPage == NULL) {\r
320 goto Done;\r
321 }\r
322\r
323 //\r
324 // Carve up new page into free pool blocks\r
325 //\r
162ed594 326 Offset = 0;\r
327 while (Offset < DEFAULT_PAGE_ALLOCATION) {\r
28a00297 328 ASSERT (Index < MAX_POOL_LIST);\r
329 FSize = LIST_TO_SIZE(Index);\r
330\r
162ed594 331 while (Offset + FSize <= DEFAULT_PAGE_ALLOCATION) {\r
022c6d45 332 Free = (POOL_FREE *) &NewPage[Offset];\r
28a00297 333 Free->Signature = POOL_FREE_SIGNATURE;\r
334 Free->Index = (UINT32)Index;\r
335 InsertHeadList (&Pool->FreeList[Index], &Free->Link);\r
162ed594 336 Offset += FSize;\r
28a00297 337 }\r
338\r
339 Index -= 1;\r
340 }\r
341\r
162ed594 342 ASSERT (Offset == DEFAULT_PAGE_ALLOCATION);\r
28a00297 343 Index = SIZE_TO_LIST(Size);\r
344 }\r
345\r
346 //\r
347 // Remove entry from free pool list\r
348 //\r
349 Free = CR (Pool->FreeList[Index].ForwardLink, POOL_FREE, Link, POOL_FREE_SIGNATURE);\r
350 RemoveEntryList (&Free->Link);\r
351\r
352 Head = (POOL_HEAD *) Free;\r
353\r
354Done:\r
355 Buffer = NULL;\r
356\r
357 if (Head != NULL) {\r
022c6d45 358\r
28a00297 359 //\r
360 // If we have a pool buffer, fill in the header & tail info\r
361 //\r
362 Head->Signature = POOL_HEAD_SIGNATURE;\r
bb683bf4 363 Head->Size = Size;\r
28a00297 364 Head->Type = (EFI_MEMORY_TYPE) PoolType;\r
365 Tail = HEAD_TO_TAIL (Head);\r
366 Tail->Signature = POOL_TAIL_SIGNATURE;\r
bb683bf4 367 Tail->Size = Size;\r
28a00297 368 Buffer = Head->Data;\r
369 DEBUG_CLEAR_MEMORY (Buffer, Size - POOL_OVERHEAD);\r
370\r
e94a9ff7 371 DEBUG ((\r
372 DEBUG_POOL,\r
57b4ecb9 373 "AllocatePoolI: Type %x, Addr %p (len %lx) %,ld\n", PoolType,\r
022c6d45 374 Buffer,\r
57b4ecb9 375 (UINT64)(Size - POOL_OVERHEAD),\r
376 (UINT64) Pool->Used\r
e94a9ff7 377 ));\r
28a00297 378\r
379 //\r
380 // Account the allocation\r
381 //\r
382 Pool->Used += Size;\r
383\r
384 } else {\r
57b4ecb9 385 DEBUG ((DEBUG_ERROR | DEBUG_POOL, "AllocatePool: failed to allocate %ld bytes\n", (UINT64) Size));\r
28a00297 386 }\r
387\r
388 return Buffer;\r
389}\r
022c6d45 390\r
28a00297 391\r
392\r
162ed594 393/**\r
28a00297 394 Frees pool.\r
395\r
022c6d45 396 @param Buffer The allocated pool entry to free\r
28a00297 397\r
022c6d45 398 @retval EFI_INVALID_PARAMETER Buffer is not a valid value.\r
162ed594 399 @retval EFI_SUCCESS Pool successfully freed.\r
28a00297 400\r
162ed594 401**/\r
402EFI_STATUS\r
403EFIAPI\r
84edd20b 404CoreInternalFreePool (\r
162ed594 405 IN VOID *Buffer\r
406 )\r
28a00297 407{\r
408 EFI_STATUS Status;\r
409\r
e94a9ff7 410 if (Buffer == NULL) {\r
28a00297 411 return EFI_INVALID_PARAMETER;\r
412 }\r
413\r
414 CoreAcquireMemoryLock ();\r
415 Status = CoreFreePoolI (Buffer);\r
416 CoreReleaseMemoryLock ();\r
417 return Status;\r
418}\r
419\r
84edd20b
SZ
420/**\r
421 Frees pool.\r
422\r
423 @param Buffer The allocated pool entry to free\r
424\r
425 @retval EFI_INVALID_PARAMETER Buffer is not a valid value.\r
426 @retval EFI_SUCCESS Pool successfully freed.\r
427\r
428**/\r
429EFI_STATUS\r
430EFIAPI\r
431CoreFreePool (\r
432 IN VOID *Buffer\r
433 )\r
434{\r
435 EFI_STATUS Status;\r
736a692e
HT
436\r
437 Status = CoreInternalFreePool (Buffer);\r
438 if (!EFI_ERROR (Status)) {\r
439 CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionFreePool, (EFI_MEMORY_TYPE) 0, 0, Buffer);\r
440 }\r
441 return Status;\r
442}\r
28a00297 443\r
162ed594 444/**\r
28a00297 445 Internal function to free a pool entry.\r
28a00297 446 Caller must have the memory lock held\r
447\r
022c6d45 448 @param Buffer The allocated pool entry to free\r
28a00297 449\r
022c6d45 450 @retval EFI_INVALID_PARAMETER Buffer not valid\r
162ed594 451 @retval EFI_SUCCESS Buffer successfully freed.\r
28a00297 452\r
162ed594 453**/\r
454EFI_STATUS\r
455CoreFreePoolI (\r
456 IN VOID *Buffer\r
457 )\r
28a00297 458{\r
459 POOL *Pool;\r
460 POOL_HEAD *Head;\r
461 POOL_TAIL *Tail;\r
462 POOL_FREE *Free;\r
463 UINTN Index;\r
464 UINTN NoPages;\r
465 UINTN Size;\r
466 CHAR8 *NewPage;\r
467 UINTN FSize;\r
162ed594 468 UINTN Offset;\r
28a00297 469 BOOLEAN AllFree;\r
470\r
57b4ecb9 471 ASSERT(Buffer != NULL);\r
28a00297 472 //\r
473 // Get the head & tail of the pool entry\r
474 //\r
475 Head = CR (Buffer, POOL_HEAD, Data, POOL_HEAD_SIGNATURE);\r
57b4ecb9 476 ASSERT(Head != NULL);\r
28a00297 477\r
478 if (Head->Signature != POOL_HEAD_SIGNATURE) {\r
479 return EFI_INVALID_PARAMETER;\r
480 }\r
481\r
482 Tail = HEAD_TO_TAIL (Head);\r
57b4ecb9 483 ASSERT(Tail != NULL);\r
28a00297 484\r
485 //\r
486 // Debug\r
487 //\r
488 ASSERT (Tail->Signature == POOL_TAIL_SIGNATURE);\r
489 ASSERT (Head->Size == Tail->Size);\r
490 ASSERT_LOCKED (&gMemoryLock);\r
491\r
492 if (Tail->Signature != POOL_TAIL_SIGNATURE) {\r
493 return EFI_INVALID_PARAMETER;\r
494 }\r
495\r
496 if (Head->Size != Tail->Size) {\r
497 return EFI_INVALID_PARAMETER;\r
498 }\r
499\r
500 //\r
501 // Determine the pool type and account for it\r
502 //\r
503 Size = Head->Size;\r
504 Pool = LookupPoolHead (Head->Type);\r
505 if (Pool == NULL) {\r
506 return EFI_INVALID_PARAMETER;\r
507 }\r
508 Pool->Used -= Size;\r
57b4ecb9 509 DEBUG ((DEBUG_POOL, "FreePool: %p (len %lx) %,ld\n", Head->Data, (UINT64)(Head->Size - POOL_OVERHEAD), (UINT64) Pool->Used));\r
28a00297 510\r
511 //\r
022c6d45 512 // Determine the pool list\r
28a00297 513 //\r
514 Index = SIZE_TO_LIST(Size);\r
515 DEBUG_CLEAR_MEMORY (Head, Size);\r
516\r
517 //\r
518 // If it's not on the list, it must be pool pages\r
519 //\r
520 if (Index >= MAX_POOL_LIST) {\r
521\r
522 //\r
523 // Return the memory pages back to free memory\r
524 //\r
525 NoPages = EFI_SIZE_TO_PAGES(Size) + EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION) - 1;\r
6e1e5405 526 NoPages &= ~(UINTN)(EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION) - 1);\r
28a00297 527 CoreFreePoolPages ((EFI_PHYSICAL_ADDRESS) (UINTN) Head, NoPages);\r
528\r
529 } else {\r
530\r
531 //\r
532 // Put the pool entry onto the free pool list\r
533 //\r
534 Free = (POOL_FREE *) Head;\r
57b4ecb9 535 ASSERT(Free != NULL);\r
28a00297 536 Free->Signature = POOL_FREE_SIGNATURE;\r
537 Free->Index = (UINT32)Index;\r
538 InsertHeadList (&Pool->FreeList[Index], &Free->Link);\r
539\r
540 //\r
022c6d45 541 // See if all the pool entries in the same page as Free are freed pool\r
28a00297 542 // entries\r
543 //\r
544 NewPage = (CHAR8 *)((UINTN)Free & ~((DEFAULT_PAGE_ALLOCATION) -1));\r
545 Free = (POOL_FREE *) &NewPage[0];\r
e94a9ff7 546 ASSERT(Free != NULL);\r
28a00297 547\r
548 if (Free->Signature == POOL_FREE_SIGNATURE) {\r
549\r
550 Index = Free->Index;\r
551\r
552 AllFree = TRUE;\r
162ed594 553 Offset = 0;\r
022c6d45 554\r
162ed594 555 while ((Offset < DEFAULT_PAGE_ALLOCATION) && (AllFree)) {\r
28a00297 556 FSize = LIST_TO_SIZE(Index);\r
162ed594 557 while (Offset + FSize <= DEFAULT_PAGE_ALLOCATION) {\r
558 Free = (POOL_FREE *) &NewPage[Offset];\r
57b4ecb9 559 ASSERT(Free != NULL);\r
28a00297 560 if (Free->Signature != POOL_FREE_SIGNATURE) {\r
561 AllFree = FALSE;\r
562 }\r
162ed594 563 Offset += FSize;\r
28a00297 564 }\r
565 Index -= 1;\r
566 }\r
567\r
568 if (AllFree) {\r
569\r
570 //\r
022c6d45 571 // All of the pool entries in the same page as Free are free pool\r
28a00297 572 // entries\r
573 // Remove all of these pool entries from the free loop lists.\r
574 //\r
575 Free = (POOL_FREE *) &NewPage[0];\r
57b4ecb9 576 ASSERT(Free != NULL);\r
28a00297 577 Index = Free->Index;\r
162ed594 578 Offset = 0;\r
022c6d45 579\r
162ed594 580 while (Offset < DEFAULT_PAGE_ALLOCATION) {\r
28a00297 581 FSize = LIST_TO_SIZE(Index);\r
162ed594 582 while (Offset + FSize <= DEFAULT_PAGE_ALLOCATION) {\r
583 Free = (POOL_FREE *) &NewPage[Offset];\r
57b4ecb9 584 ASSERT(Free != NULL);\r
28a00297 585 RemoveEntryList (&Free->Link);\r
162ed594 586 Offset += FSize;\r
28a00297 587 }\r
588 Index -= 1;\r
589 }\r
590\r
591 //\r
592 // Free the page\r
593 //\r
594 CoreFreePoolPages ((EFI_PHYSICAL_ADDRESS) (UINTN)NewPage, EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION));\r
595 }\r
596 }\r
597 }\r
598\r
599 //\r
022c6d45 600 // If this is an OS specific memory type, then check to see if the last\r
28a00297 601 // portion of that memory type has been freed. If it has, then free the\r
602 // list entry for that memory type\r
603 //\r
3d78c020 604 if ((INT32)Pool->MemoryType < 0 && Pool->Used == 0) {\r
28a00297 605 RemoveEntryList (&Pool->Link);\r
606 CoreFreePoolI (Pool);\r
607 }\r
608\r
609 return EFI_SUCCESS;\r
610}\r
84edd20b 611\r