]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Core/Dxe/Mem/Pool.c
ShellPkg: Fix typos and EDK2 coding style issues
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Mem / Pool.c
... / ...
CommitLineData
1/** @file\r
2 UEFI Memory pool management functions.\r
3\r
4Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials\r
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
12\r
13**/\r
14\r
15#include "DxeMain.h"\r
16#include "Imem.h"\r
17\r
18#define POOL_FREE_SIGNATURE SIGNATURE_32('p','f','r','0')\r
19typedef struct {\r
20 UINT32 Signature;\r
21 UINT32 Index;\r
22 LIST_ENTRY Link;\r
23} POOL_FREE;\r
24\r
25\r
26#define POOL_HEAD_SIGNATURE SIGNATURE_32('p','h','d','0')\r
27typedef struct {\r
28 UINT32 Signature;\r
29 UINT32 Reserved;\r
30 EFI_MEMORY_TYPE Type;\r
31 UINTN Size;\r
32 CHAR8 Data[1];\r
33} POOL_HEAD;\r
34\r
35#define SIZE_OF_POOL_HEAD OFFSET_OF(POOL_HEAD,Data)\r
36\r
37#define POOL_TAIL_SIGNATURE SIGNATURE_32('p','t','a','l')\r
38typedef struct {\r
39 UINT32 Signature;\r
40 UINT32 Reserved;\r
41 UINTN Size;\r
42} POOL_TAIL;\r
43\r
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
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
57\r
58#define SIZE_TO_LIST(a) (GetPoolIndexFromSize (a))\r
59#define LIST_TO_SIZE(a) (mPoolSizeTable [a])\r
60\r
61#define MAX_POOL_LIST (sizeof (mPoolSizeTable) / sizeof (mPoolSizeTable[0]))\r
62\r
63#define MAX_POOL_SIZE (MAX_ADDRESS - POOL_OVERHEAD)\r
64\r
65//\r
66// Globals\r
67//\r
68\r
69#define POOL_SIGNATURE SIGNATURE_32('p','l','s','t')\r
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
76} POOL;\r
77\r
78//\r
79// Pool header for each memory type.\r
80//\r
81POOL mPoolHead[EfiMaxMemoryType];\r
82\r
83//\r
84// List of pool header to search for the appropriate memory type.\r
85//\r
86LIST_ENTRY mPoolHeadList = INITIALIZE_LIST_HEAD_VARIABLE (mPoolHeadList);\r
87\r
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
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
111\r
112/**\r
113 Called to initialize the pool.\r
114\r
115**/\r
116VOID\r
117CoreInitializePool (\r
118 VOID\r
119 )\r
120{\r
121 UINTN Type;\r
122 UINTN Index;\r
123\r
124 for (Type=0; Type < EfiMaxMemoryType; Type++) {\r
125 mPoolHead[Type].Signature = 0;\r
126 mPoolHead[Type].Used = 0;\r
127 mPoolHead[Type].MemoryType = (EFI_MEMORY_TYPE) Type;\r
128 for (Index=0; Index < MAX_POOL_LIST; Index++) {\r
129 InitializeListHead (&mPoolHead[Type].FreeList[Index]);\r
130 }\r
131 }\r
132}\r
133\r
134\r
135/**\r
136 Look up pool head for specified memory type.\r
137\r
138 @param MemoryType Memory type of which pool head is looked for\r
139\r
140 @return Pointer of Corresponding pool head.\r
141\r
142**/\r
143POOL *\r
144LookupPoolHead (\r
145 IN EFI_MEMORY_TYPE MemoryType\r
146 )\r
147{\r
148 LIST_ENTRY *Link;\r
149 POOL *Pool;\r
150 UINTN Index;\r
151\r
152 if ((UINT32)MemoryType < EfiMaxMemoryType) {\r
153 return &mPoolHead[MemoryType];\r
154 }\r
155\r
156 //\r
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
160 //\r
161 if ((UINT32) MemoryType >= MEMORY_TYPE_OEM_RESERVED_MIN) {\r
162\r
163 for (Link = mPoolHeadList.ForwardLink; Link != &mPoolHeadList; Link = Link->ForwardLink) {\r
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
182 InsertHeadList (&mPoolHeadList, &Pool->Link);\r
183\r
184 return Pool;\r
185 }\r
186\r
187 return NULL;\r
188}\r
189\r
190\r
191\r
192/**\r
193 Allocate pool of a particular type.\r
194\r
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
199\r
200 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
201 PoolType is in the range EfiMaxMemoryType..0x6FFFFFFF.\r
202 PoolType is EfiPersistentMemory.\r
203 @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.\r
204 @retval EFI_SUCCESS Pool successfully allocated.\r
205\r
206**/\r
207EFI_STATUS\r
208EFIAPI\r
209CoreInternalAllocatePool (\r
210 IN EFI_MEMORY_TYPE PoolType,\r
211 IN UINTN Size,\r
212 OUT VOID **Buffer\r
213 )\r
214{\r
215 EFI_STATUS Status;\r
216\r
217 //\r
218 // If it's not a valid type, fail it\r
219 //\r
220 if ((PoolType >= EfiMaxMemoryType && PoolType < MEMORY_TYPE_OEM_RESERVED_MIN) ||\r
221 (PoolType == EfiConventionalMemory) || (PoolType == EfiPersistentMemory)) {\r
222 return EFI_INVALID_PARAMETER;\r
223 }\r
224\r
225 if (Buffer == NULL) {\r
226 return EFI_INVALID_PARAMETER;\r
227 }\r
228\r
229 *Buffer = NULL;\r
230\r
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
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
260 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
261 PoolType is in the range EfiMaxMemoryType..0x6FFFFFFF.\r
262 PoolType is EfiPersistentMemory.\r
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
276\r
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 InstallMemoryAttributesTableOnMemoryAllocation (PoolType);\r
281 }\r
282 return Status;\r
283}\r
284\r
285/**\r
286 Internal function to allocate pool of a particular type.\r
287 Caller must have the memory lock held\r
288\r
289 @param PoolType Type of pool to allocate\r
290 @param Size The amount of pool to allocate\r
291\r
292 @return The allocate pool, or NULL\r
293\r
294**/\r
295VOID *\r
296CoreAllocatePoolI (\r
297 IN EFI_MEMORY_TYPE PoolType,\r
298 IN UINTN Size\r
299 )\r
300{\r
301 POOL *Pool;\r
302 POOL_FREE *Free;\r
303 POOL_HEAD *Head;\r
304 POOL_TAIL *Tail;\r
305 CHAR8 *NewPage;\r
306 VOID *Buffer;\r
307 UINTN Index;\r
308 UINTN FSize;\r
309 UINTN Offset, MaxOffset;\r
310 UINTN NoPages;\r
311 UINTN Granularity;\r
312\r
313 ASSERT_LOCKED (&gMemoryLock);\r
314\r
315 if (PoolType == EfiACPIReclaimMemory ||\r
316 PoolType == EfiACPIMemoryNVS ||\r
317 PoolType == EfiRuntimeServicesCode ||\r
318 PoolType == EfiRuntimeServicesData) {\r
319\r
320 Granularity = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT;\r
321 } else {\r
322 Granularity = DEFAULT_PAGE_ALLOCATION;\r
323 }\r
324\r
325 //\r
326 // Adjust the size by the pool header & tail overhead\r
327 //\r
328\r
329 //\r
330 // Adjusting the Size to be of proper alignment so that\r
331 // we don't get an unaligned access fault later when\r
332 // pool_Tail is being initialized\r
333 //\r
334 Size = ALIGN_VARIABLE (Size);\r
335\r
336 Size += POOL_OVERHEAD;\r
337 Index = SIZE_TO_LIST(Size);\r
338 Pool = LookupPoolHead (PoolType);\r
339 if (Pool== NULL) {\r
340 return NULL;\r
341 }\r
342 Head = NULL;\r
343\r
344 //\r
345 // If allocation is over max size, just allocate pages for the request\r
346 // (slow)\r
347 //\r
348 if (Index >= SIZE_TO_LIST (Granularity)) {\r
349 NoPages = EFI_SIZE_TO_PAGES(Size) + EFI_SIZE_TO_PAGES (Granularity) - 1;\r
350 NoPages &= ~(UINTN)(EFI_SIZE_TO_PAGES (Granularity) - 1);\r
351 Head = CoreAllocatePoolPages (PoolType, NoPages, Granularity);\r
352 goto Done;\r
353 }\r
354\r
355 //\r
356 // If there's no free pool in the proper list size, go get some more pages\r
357 //\r
358 if (IsListEmpty (&Pool->FreeList[Index])) {\r
359\r
360 Offset = LIST_TO_SIZE (Index);\r
361 MaxOffset = Granularity;\r
362\r
363 //\r
364 // Check the bins holding larger blocks, and carve one up if needed\r
365 //\r
366 while (++Index < SIZE_TO_LIST (Granularity)) {\r
367 if (!IsListEmpty (&Pool->FreeList[Index])) {\r
368 Free = CR (Pool->FreeList[Index].ForwardLink, POOL_FREE, Link, POOL_FREE_SIGNATURE);\r
369 RemoveEntryList (&Free->Link);\r
370 NewPage = (VOID *) Free;\r
371 MaxOffset = LIST_TO_SIZE (Index);\r
372 goto Carve;\r
373 }\r
374 }\r
375\r
376 //\r
377 // Get another page\r
378 //\r
379 NewPage = CoreAllocatePoolPages(PoolType, EFI_SIZE_TO_PAGES (Granularity), Granularity);\r
380 if (NewPage == NULL) {\r
381 goto Done;\r
382 }\r
383\r
384 //\r
385 // Serve the allocation request from the head of the allocated block\r
386 //\r
387Carve:\r
388 Head = (POOL_HEAD *) NewPage;\r
389\r
390 //\r
391 // Carve up remaining space into free pool blocks\r
392 //\r
393 Index--;\r
394 while (Offset < MaxOffset) {\r
395 ASSERT (Index < MAX_POOL_LIST);\r
396 FSize = LIST_TO_SIZE(Index);\r
397\r
398 while (Offset + FSize <= MaxOffset) {\r
399 Free = (POOL_FREE *) &NewPage[Offset];\r
400 Free->Signature = POOL_FREE_SIGNATURE;\r
401 Free->Index = (UINT32)Index;\r
402 InsertHeadList (&Pool->FreeList[Index], &Free->Link);\r
403 Offset += FSize;\r
404 }\r
405 Index -= 1;\r
406 }\r
407\r
408 ASSERT (Offset == MaxOffset);\r
409 goto Done;\r
410 }\r
411\r
412 //\r
413 // Remove entry from free pool list\r
414 //\r
415 Free = CR (Pool->FreeList[Index].ForwardLink, POOL_FREE, Link, POOL_FREE_SIGNATURE);\r
416 RemoveEntryList (&Free->Link);\r
417\r
418 Head = (POOL_HEAD *) Free;\r
419\r
420Done:\r
421 Buffer = NULL;\r
422\r
423 if (Head != NULL) {\r
424\r
425 //\r
426 // If we have a pool buffer, fill in the header & tail info\r
427 //\r
428 Head->Signature = POOL_HEAD_SIGNATURE;\r
429 Head->Size = Size;\r
430 Head->Type = (EFI_MEMORY_TYPE) PoolType;\r
431 Tail = HEAD_TO_TAIL (Head);\r
432 Tail->Signature = POOL_TAIL_SIGNATURE;\r
433 Tail->Size = Size;\r
434 Buffer = Head->Data;\r
435 DEBUG_CLEAR_MEMORY (Buffer, Size - POOL_OVERHEAD);\r
436\r
437 DEBUG ((\r
438 DEBUG_POOL,\r
439 "AllocatePoolI: Type %x, Addr %p (len %lx) %,ld\n", PoolType,\r
440 Buffer,\r
441 (UINT64)(Size - POOL_OVERHEAD),\r
442 (UINT64) Pool->Used\r
443 ));\r
444\r
445 //\r
446 // Account the allocation\r
447 //\r
448 Pool->Used += Size;\r
449\r
450 } else {\r
451 DEBUG ((DEBUG_ERROR | DEBUG_POOL, "AllocatePool: failed to allocate %ld bytes\n", (UINT64) Size));\r
452 }\r
453\r
454 return Buffer;\r
455}\r
456\r
457\r
458\r
459/**\r
460 Frees pool.\r
461\r
462 @param Buffer The allocated pool entry to free\r
463 @param PoolType Pointer to pool type\r
464\r
465 @retval EFI_INVALID_PARAMETER Buffer is not a valid value.\r
466 @retval EFI_SUCCESS Pool successfully freed.\r
467\r
468**/\r
469EFI_STATUS\r
470EFIAPI\r
471CoreInternalFreePool (\r
472 IN VOID *Buffer,\r
473 OUT EFI_MEMORY_TYPE *PoolType OPTIONAL\r
474 )\r
475{\r
476 EFI_STATUS Status;\r
477\r
478 if (Buffer == NULL) {\r
479 return EFI_INVALID_PARAMETER;\r
480 }\r
481\r
482 CoreAcquireMemoryLock ();\r
483 Status = CoreFreePoolI (Buffer, PoolType);\r
484 CoreReleaseMemoryLock ();\r
485 return Status;\r
486}\r
487\r
488/**\r
489 Frees pool.\r
490\r
491 @param Buffer The allocated pool entry to free\r
492\r
493 @retval EFI_INVALID_PARAMETER Buffer is not a valid value.\r
494 @retval EFI_SUCCESS Pool successfully freed.\r
495\r
496**/\r
497EFI_STATUS\r
498EFIAPI\r
499CoreFreePool (\r
500 IN VOID *Buffer\r
501 )\r
502{\r
503 EFI_STATUS Status;\r
504 EFI_MEMORY_TYPE PoolType;\r
505\r
506 Status = CoreInternalFreePool (Buffer, &PoolType);\r
507 if (!EFI_ERROR (Status)) {\r
508 CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionFreePool, PoolType, 0, Buffer);\r
509 InstallMemoryAttributesTableOnMemoryAllocation (PoolType);\r
510 }\r
511 return Status;\r
512}\r
513\r
514/**\r
515 Internal function to free a pool entry.\r
516 Caller must have the memory lock held\r
517\r
518 @param Buffer The allocated pool entry to free\r
519 @param PoolType Pointer to pool type\r
520\r
521 @retval EFI_INVALID_PARAMETER Buffer not valid\r
522 @retval EFI_SUCCESS Buffer successfully freed.\r
523\r
524**/\r
525EFI_STATUS\r
526CoreFreePoolI (\r
527 IN VOID *Buffer,\r
528 OUT EFI_MEMORY_TYPE *PoolType OPTIONAL\r
529 )\r
530{\r
531 POOL *Pool;\r
532 POOL_HEAD *Head;\r
533 POOL_TAIL *Tail;\r
534 POOL_FREE *Free;\r
535 UINTN Index;\r
536 UINTN NoPages;\r
537 UINTN Size;\r
538 CHAR8 *NewPage;\r
539 UINTN Offset;\r
540 BOOLEAN AllFree;\r
541 UINTN Granularity;\r
542\r
543 ASSERT(Buffer != NULL);\r
544 //\r
545 // Get the head & tail of the pool entry\r
546 //\r
547 Head = CR (Buffer, POOL_HEAD, Data, POOL_HEAD_SIGNATURE);\r
548 ASSERT(Head != NULL);\r
549\r
550 if (Head->Signature != POOL_HEAD_SIGNATURE) {\r
551 return EFI_INVALID_PARAMETER;\r
552 }\r
553\r
554 Tail = HEAD_TO_TAIL (Head);\r
555 ASSERT(Tail != NULL);\r
556\r
557 //\r
558 // Debug\r
559 //\r
560 ASSERT (Tail->Signature == POOL_TAIL_SIGNATURE);\r
561 ASSERT (Head->Size == Tail->Size);\r
562 ASSERT_LOCKED (&gMemoryLock);\r
563\r
564 if (Tail->Signature != POOL_TAIL_SIGNATURE) {\r
565 return EFI_INVALID_PARAMETER;\r
566 }\r
567\r
568 if (Head->Size != Tail->Size) {\r
569 return EFI_INVALID_PARAMETER;\r
570 }\r
571\r
572 //\r
573 // Determine the pool type and account for it\r
574 //\r
575 Size = Head->Size;\r
576 Pool = LookupPoolHead (Head->Type);\r
577 if (Pool == NULL) {\r
578 return EFI_INVALID_PARAMETER;\r
579 }\r
580 Pool->Used -= Size;\r
581 DEBUG ((DEBUG_POOL, "FreePool: %p (len %lx) %,ld\n", Head->Data, (UINT64)(Head->Size - POOL_OVERHEAD), (UINT64) Pool->Used));\r
582\r
583 if (Head->Type == EfiACPIReclaimMemory ||\r
584 Head->Type == EfiACPIMemoryNVS ||\r
585 Head->Type == EfiRuntimeServicesCode ||\r
586 Head->Type == EfiRuntimeServicesData) {\r
587\r
588 Granularity = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT;\r
589 } else {\r
590 Granularity = DEFAULT_PAGE_ALLOCATION;\r
591 }\r
592\r
593 if (PoolType != NULL) {\r
594 *PoolType = Head->Type;\r
595 }\r
596\r
597 //\r
598 // Determine the pool list\r
599 //\r
600 Index = SIZE_TO_LIST(Size);\r
601 DEBUG_CLEAR_MEMORY (Head, Size);\r
602\r
603 //\r
604 // If it's not on the list, it must be pool pages\r
605 //\r
606 if (Index >= SIZE_TO_LIST (Granularity)) {\r
607\r
608 //\r
609 // Return the memory pages back to free memory\r
610 //\r
611 NoPages = EFI_SIZE_TO_PAGES(Size) + EFI_SIZE_TO_PAGES (Granularity) - 1;\r
612 NoPages &= ~(UINTN)(EFI_SIZE_TO_PAGES (Granularity) - 1);\r
613 CoreFreePoolPages ((EFI_PHYSICAL_ADDRESS) (UINTN) Head, NoPages);\r
614\r
615 } else {\r
616\r
617 //\r
618 // Put the pool entry onto the free pool list\r
619 //\r
620 Free = (POOL_FREE *) Head;\r
621 ASSERT(Free != NULL);\r
622 Free->Signature = POOL_FREE_SIGNATURE;\r
623 Free->Index = (UINT32)Index;\r
624 InsertHeadList (&Pool->FreeList[Index], &Free->Link);\r
625\r
626 //\r
627 // See if all the pool entries in the same page as Free are freed pool\r
628 // entries\r
629 //\r
630 NewPage = (CHAR8 *)((UINTN)Free & ~(Granularity - 1));\r
631 Free = (POOL_FREE *) &NewPage[0];\r
632 ASSERT(Free != NULL);\r
633\r
634 if (Free->Signature == POOL_FREE_SIGNATURE) {\r
635\r
636 AllFree = TRUE;\r
637 Offset = 0;\r
638\r
639 while ((Offset < Granularity) && (AllFree)) {\r
640 Free = (POOL_FREE *) &NewPage[Offset];\r
641 ASSERT(Free != NULL);\r
642 if (Free->Signature != POOL_FREE_SIGNATURE) {\r
643 AllFree = FALSE;\r
644 }\r
645 Offset += LIST_TO_SIZE(Free->Index);\r
646 }\r
647\r
648 if (AllFree) {\r
649\r
650 //\r
651 // All of the pool entries in the same page as Free are free pool\r
652 // entries\r
653 // Remove all of these pool entries from the free loop lists.\r
654 //\r
655 Free = (POOL_FREE *) &NewPage[0];\r
656 ASSERT(Free != NULL);\r
657 Offset = 0;\r
658\r
659 while (Offset < Granularity) {\r
660 Free = (POOL_FREE *) &NewPage[Offset];\r
661 ASSERT(Free != NULL);\r
662 RemoveEntryList (&Free->Link);\r
663 Offset += LIST_TO_SIZE(Free->Index);\r
664 }\r
665\r
666 //\r
667 // Free the page\r
668 //\r
669 CoreFreePoolPages ((EFI_PHYSICAL_ADDRESS) (UINTN)NewPage, EFI_SIZE_TO_PAGES (Granularity));\r
670 }\r
671 }\r
672 }\r
673\r
674 //\r
675 // If this is an OS/OEM specific memory type, then check to see if the last\r
676 // portion of that memory type has been freed. If it has, then free the\r
677 // list entry for that memory type\r
678 //\r
679 if (((UINT32) Pool->MemoryType >= MEMORY_TYPE_OEM_RESERVED_MIN) && Pool->Used == 0) {\r
680 RemoveEntryList (&Pool->Link);\r
681 CoreFreePoolI (Pool, NULL);\r
682 }\r
683\r
684 return EFI_SUCCESS;\r
685}\r
686\r