]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Mem/Pool.c
ArmPkg: DefaultExceptionHandler fixes for use with DxeCore
[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
a671a012 4Copyright (c) 2006 - 2015, 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
3e058701 200 @retval EFI_INVALID_PARAMETER PoolType not valid or Buffer is NULL. \r
a671a012 201 PoolType was EfiPersistentMemory.\r
022c6d45 202 @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.\r
162ed594 203 @retval EFI_SUCCESS Pool successfully allocated.\r
204\r
205**/\r
28a00297 206EFI_STATUS\r
207EFIAPI\r
84edd20b 208CoreInternalAllocatePool (\r
28a00297 209 IN EFI_MEMORY_TYPE PoolType,\r
210 IN UINTN Size,\r
211 OUT VOID **Buffer\r
212 )\r
28a00297 213{\r
214 EFI_STATUS Status;\r
215\r
216 //\r
217 // If it's not a valid type, fail it\r
218 //\r
8ee25f48 219 if ((PoolType >= EfiMaxMemoryType && PoolType < MEMORY_TYPE_OEM_RESERVED_MIN) ||\r
a671a012 220 (PoolType == EfiConventionalMemory) || (PoolType == EfiPersistentMemory)) {\r
28a00297 221 return EFI_INVALID_PARAMETER;\r
222 }\r
022c6d45 223\r
3e058701
ED
224 if (Buffer == NULL) {\r
225 return EFI_INVALID_PARAMETER;\r
226 }\r
227\r
28a00297 228 *Buffer = NULL;\r
022c6d45 229\r
28a00297 230 //\r
231 // If size is too large, fail it\r
232 // Base on the EFI spec, return status of EFI_OUT_OF_RESOURCES\r
233 //\r
234 if (Size > MAX_POOL_SIZE) {\r
235 return EFI_OUT_OF_RESOURCES;\r
236 }\r
237\r
238 //\r
239 // Acquire the memory lock and make the allocation\r
240 //\r
241 Status = CoreAcquireLockOrFail (&gMemoryLock);\r
242 if (EFI_ERROR (Status)) {\r
243 return EFI_OUT_OF_RESOURCES;\r
244 }\r
245\r
246 *Buffer = CoreAllocatePoolI (PoolType, Size);\r
247 CoreReleaseMemoryLock ();\r
248 return (*Buffer != NULL) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES;\r
249}\r
250\r
84edd20b
SZ
251/**\r
252 Allocate pool of a particular type.\r
253\r
254 @param PoolType Type of pool to allocate\r
255 @param Size The amount of pool to allocate\r
256 @param Buffer The address to return a pointer to the allocated\r
257 pool\r
258\r
259 @retval EFI_INVALID_PARAMETER PoolType not valid or Buffer is NULL. \r
260 @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.\r
261 @retval EFI_SUCCESS Pool successfully allocated.\r
262\r
263**/\r
264EFI_STATUS\r
265EFIAPI\r
266CoreAllocatePool (\r
267 IN EFI_MEMORY_TYPE PoolType,\r
268 IN UINTN Size,\r
269 OUT VOID **Buffer\r
270 )\r
271{\r
272 EFI_STATUS Status;\r
28a00297 273\r
84edd20b
SZ
274 Status = CoreInternalAllocatePool (PoolType, Size, Buffer);\r
275 if (!EFI_ERROR (Status)) {\r
276 CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionAllocatePool, PoolType, Size, *Buffer);\r
277 }\r
278 return Status;\r
279}\r
28a00297 280\r
162ed594 281/**\r
28a00297 282 Internal function to allocate pool of a particular type.\r
28a00297 283 Caller must have the memory lock held\r
284\r
022c6d45 285 @param PoolType Type of pool to allocate\r
286 @param Size The amount of pool to allocate\r
28a00297 287\r
162ed594 288 @return The allocate pool, or NULL\r
28a00297 289\r
162ed594 290**/\r
291VOID *\r
292CoreAllocatePoolI (\r
293 IN EFI_MEMORY_TYPE PoolType,\r
294 IN UINTN Size\r
295 )\r
28a00297 296{\r
297 POOL *Pool;\r
298 POOL_FREE *Free;\r
299 POOL_HEAD *Head;\r
300 POOL_TAIL *Tail;\r
301 CHAR8 *NewPage;\r
302 VOID *Buffer;\r
303 UINTN Index;\r
304 UINTN FSize;\r
6860b92c 305 UINTN Offset, MaxOffset;\r
28a00297 306 UINTN NoPages;\r
7970100c 307 UINTN Granularity;\r
28a00297 308\r
309 ASSERT_LOCKED (&gMemoryLock);\r
310\r
7970100c
AB
311 if (PoolType == EfiACPIReclaimMemory ||\r
312 PoolType == EfiACPIMemoryNVS ||\r
313 PoolType == EfiRuntimeServicesCode ||\r
314 PoolType == EfiRuntimeServicesData) {\r
315\r
316 Granularity = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT;\r
317 } else {\r
318 Granularity = DEFAULT_PAGE_ALLOCATION;\r
319 }\r
320\r
28a00297 321 //\r
322 // Adjust the size by the pool header & tail overhead\r
323 //\r
022c6d45 324\r
28a00297 325 //\r
326 // Adjusting the Size to be of proper alignment so that\r
327 // we don't get an unaligned access fault later when\r
328 // pool_Tail is being initialized\r
329 //\r
f0d5cbb6 330 Size = ALIGN_VARIABLE (Size);\r
28a00297 331\r
332 Size += POOL_OVERHEAD;\r
333 Index = SIZE_TO_LIST(Size);\r
334 Pool = LookupPoolHead (PoolType);\r
335 if (Pool== NULL) {\r
336 return NULL;\r
337 }\r
338 Head = NULL;\r
339\r
340 //\r
341 // If allocation is over max size, just allocate pages for the request\r
342 // (slow)\r
343 //\r
f2c7daf6 344 if (Index >= SIZE_TO_LIST (Granularity)) {\r
7970100c
AB
345 NoPages = EFI_SIZE_TO_PAGES(Size) + EFI_SIZE_TO_PAGES (Granularity) - 1;\r
346 NoPages &= ~(UINTN)(EFI_SIZE_TO_PAGES (Granularity) - 1);\r
347 Head = CoreAllocatePoolPages (PoolType, NoPages, Granularity);\r
28a00297 348 goto Done;\r
349 }\r
350\r
351 //\r
352 // If there's no free pool in the proper list size, go get some more pages\r
353 //\r
354 if (IsListEmpty (&Pool->FreeList[Index])) {\r
355\r
6860b92c
AB
356 Offset = LIST_TO_SIZE (Index);\r
357 MaxOffset = Granularity;\r
358\r
359 //\r
360 // Check the bins holding larger blocks, and carve one up if needed\r
361 //\r
362 while (++Index < SIZE_TO_LIST (Granularity)) {\r
363 if (!IsListEmpty (&Pool->FreeList[Index])) {\r
364 Free = CR (Pool->FreeList[Index].ForwardLink, POOL_FREE, Link, POOL_FREE_SIGNATURE);\r
365 RemoveEntryList (&Free->Link);\r
366 NewPage = (VOID *) Free;\r
367 MaxOffset = LIST_TO_SIZE (Index);\r
368 goto Carve;\r
369 }\r
370 }\r
371\r
28a00297 372 //\r
373 // Get another page\r
374 //\r
7970100c 375 NewPage = CoreAllocatePoolPages(PoolType, EFI_SIZE_TO_PAGES (Granularity), Granularity);\r
28a00297 376 if (NewPage == NULL) {\r
377 goto Done;\r
378 }\r
379\r
380 //\r
f8aabf6e 381 // Serve the allocation request from the head of the allocated block\r
28a00297 382 //\r
6860b92c 383Carve:\r
f8aabf6e 384 Head = (POOL_HEAD *) NewPage;\r
f8aabf6e
AB
385\r
386 //\r
387 // Carve up remaining space into free pool blocks\r
388 //\r
6860b92c
AB
389 Index--;\r
390 while (Offset < MaxOffset) {\r
28a00297 391 ASSERT (Index < MAX_POOL_LIST);\r
392 FSize = LIST_TO_SIZE(Index);\r
393\r
6860b92c 394 while (Offset + FSize <= MaxOffset) {\r
022c6d45 395 Free = (POOL_FREE *) &NewPage[Offset];\r
28a00297 396 Free->Signature = POOL_FREE_SIGNATURE;\r
397 Free->Index = (UINT32)Index;\r
398 InsertHeadList (&Pool->FreeList[Index], &Free->Link);\r
162ed594 399 Offset += FSize;\r
28a00297 400 }\r
28a00297 401 Index -= 1;\r
402 }\r
403\r
6860b92c 404 ASSERT (Offset == MaxOffset);\r
f8aabf6e 405 goto Done;\r
28a00297 406 }\r
407\r
408 //\r
409 // Remove entry from free pool list\r
410 //\r
411 Free = CR (Pool->FreeList[Index].ForwardLink, POOL_FREE, Link, POOL_FREE_SIGNATURE);\r
412 RemoveEntryList (&Free->Link);\r
413\r
414 Head = (POOL_HEAD *) Free;\r
415\r
416Done:\r
417 Buffer = NULL;\r
418\r
419 if (Head != NULL) {\r
022c6d45 420\r
28a00297 421 //\r
422 // If we have a pool buffer, fill in the header & tail info\r
423 //\r
424 Head->Signature = POOL_HEAD_SIGNATURE;\r
bb683bf4 425 Head->Size = Size;\r
28a00297 426 Head->Type = (EFI_MEMORY_TYPE) PoolType;\r
427 Tail = HEAD_TO_TAIL (Head);\r
428 Tail->Signature = POOL_TAIL_SIGNATURE;\r
bb683bf4 429 Tail->Size = Size;\r
28a00297 430 Buffer = Head->Data;\r
431 DEBUG_CLEAR_MEMORY (Buffer, Size - POOL_OVERHEAD);\r
432\r
e94a9ff7 433 DEBUG ((\r
434 DEBUG_POOL,\r
57b4ecb9 435 "AllocatePoolI: Type %x, Addr %p (len %lx) %,ld\n", PoolType,\r
022c6d45 436 Buffer,\r
57b4ecb9 437 (UINT64)(Size - POOL_OVERHEAD),\r
438 (UINT64) Pool->Used\r
e94a9ff7 439 ));\r
28a00297 440\r
441 //\r
442 // Account the allocation\r
443 //\r
444 Pool->Used += Size;\r
445\r
446 } else {\r
57b4ecb9 447 DEBUG ((DEBUG_ERROR | DEBUG_POOL, "AllocatePool: failed to allocate %ld bytes\n", (UINT64) Size));\r
28a00297 448 }\r
449\r
450 return Buffer;\r
451}\r
022c6d45 452\r
28a00297 453\r
454\r
162ed594 455/**\r
28a00297 456 Frees pool.\r
457\r
022c6d45 458 @param Buffer The allocated pool entry to free\r
28a00297 459\r
022c6d45 460 @retval EFI_INVALID_PARAMETER Buffer is not a valid value.\r
162ed594 461 @retval EFI_SUCCESS Pool successfully freed.\r
28a00297 462\r
162ed594 463**/\r
464EFI_STATUS\r
465EFIAPI\r
84edd20b 466CoreInternalFreePool (\r
162ed594 467 IN VOID *Buffer\r
468 )\r
28a00297 469{\r
470 EFI_STATUS Status;\r
471\r
e94a9ff7 472 if (Buffer == NULL) {\r
28a00297 473 return EFI_INVALID_PARAMETER;\r
474 }\r
475\r
476 CoreAcquireMemoryLock ();\r
477 Status = CoreFreePoolI (Buffer);\r
478 CoreReleaseMemoryLock ();\r
479 return Status;\r
480}\r
481\r
84edd20b
SZ
482/**\r
483 Frees pool.\r
484\r
485 @param Buffer The allocated pool entry to free\r
486\r
487 @retval EFI_INVALID_PARAMETER Buffer is not a valid value.\r
488 @retval EFI_SUCCESS Pool successfully freed.\r
489\r
490**/\r
491EFI_STATUS\r
492EFIAPI\r
493CoreFreePool (\r
494 IN VOID *Buffer\r
495 )\r
496{\r
497 EFI_STATUS Status;\r
736a692e
HT
498\r
499 Status = CoreInternalFreePool (Buffer);\r
500 if (!EFI_ERROR (Status)) {\r
501 CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionFreePool, (EFI_MEMORY_TYPE) 0, 0, Buffer);\r
502 }\r
503 return Status;\r
504}\r
28a00297 505\r
162ed594 506/**\r
28a00297 507 Internal function to free a pool entry.\r
28a00297 508 Caller must have the memory lock held\r
509\r
022c6d45 510 @param Buffer The allocated pool entry to free\r
28a00297 511\r
022c6d45 512 @retval EFI_INVALID_PARAMETER Buffer not valid\r
162ed594 513 @retval EFI_SUCCESS Buffer successfully freed.\r
28a00297 514\r
162ed594 515**/\r
516EFI_STATUS\r
517CoreFreePoolI (\r
518 IN VOID *Buffer\r
519 )\r
28a00297 520{\r
521 POOL *Pool;\r
522 POOL_HEAD *Head;\r
523 POOL_TAIL *Tail;\r
524 POOL_FREE *Free;\r
525 UINTN Index;\r
526 UINTN NoPages;\r
527 UINTN Size;\r
528 CHAR8 *NewPage;\r
162ed594 529 UINTN Offset;\r
28a00297 530 BOOLEAN AllFree;\r
7970100c 531 UINTN Granularity;\r
28a00297 532\r
57b4ecb9 533 ASSERT(Buffer != NULL);\r
28a00297 534 //\r
535 // Get the head & tail of the pool entry\r
536 //\r
537 Head = CR (Buffer, POOL_HEAD, Data, POOL_HEAD_SIGNATURE);\r
57b4ecb9 538 ASSERT(Head != NULL);\r
28a00297 539\r
540 if (Head->Signature != POOL_HEAD_SIGNATURE) {\r
541 return EFI_INVALID_PARAMETER;\r
542 }\r
543\r
544 Tail = HEAD_TO_TAIL (Head);\r
57b4ecb9 545 ASSERT(Tail != NULL);\r
28a00297 546\r
547 //\r
548 // Debug\r
549 //\r
550 ASSERT (Tail->Signature == POOL_TAIL_SIGNATURE);\r
551 ASSERT (Head->Size == Tail->Size);\r
552 ASSERT_LOCKED (&gMemoryLock);\r
553\r
554 if (Tail->Signature != POOL_TAIL_SIGNATURE) {\r
555 return EFI_INVALID_PARAMETER;\r
556 }\r
557\r
558 if (Head->Size != Tail->Size) {\r
559 return EFI_INVALID_PARAMETER;\r
560 }\r
561\r
562 //\r
563 // Determine the pool type and account for it\r
564 //\r
565 Size = Head->Size;\r
566 Pool = LookupPoolHead (Head->Type);\r
567 if (Pool == NULL) {\r
568 return EFI_INVALID_PARAMETER;\r
569 }\r
570 Pool->Used -= Size;\r
57b4ecb9 571 DEBUG ((DEBUG_POOL, "FreePool: %p (len %lx) %,ld\n", Head->Data, (UINT64)(Head->Size - POOL_OVERHEAD), (UINT64) Pool->Used));\r
28a00297 572\r
7970100c
AB
573 if (Head->Type == EfiACPIReclaimMemory ||\r
574 Head->Type == EfiACPIMemoryNVS ||\r
575 Head->Type == EfiRuntimeServicesCode ||\r
576 Head->Type == EfiRuntimeServicesData) {\r
577\r
578 Granularity = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT;\r
579 } else {\r
580 Granularity = DEFAULT_PAGE_ALLOCATION;\r
581 }\r
582\r
28a00297 583 //\r
022c6d45 584 // Determine the pool list\r
28a00297 585 //\r
586 Index = SIZE_TO_LIST(Size);\r
587 DEBUG_CLEAR_MEMORY (Head, Size);\r
588\r
589 //\r
590 // If it's not on the list, it must be pool pages\r
591 //\r
f2c7daf6 592 if (Index >= SIZE_TO_LIST (Granularity)) {\r
28a00297 593\r
594 //\r
595 // Return the memory pages back to free memory\r
596 //\r
7970100c
AB
597 NoPages = EFI_SIZE_TO_PAGES(Size) + EFI_SIZE_TO_PAGES (Granularity) - 1;\r
598 NoPages &= ~(UINTN)(EFI_SIZE_TO_PAGES (Granularity) - 1);\r
28a00297 599 CoreFreePoolPages ((EFI_PHYSICAL_ADDRESS) (UINTN) Head, NoPages);\r
600\r
601 } else {\r
602\r
603 //\r
604 // Put the pool entry onto the free pool list\r
605 //\r
606 Free = (POOL_FREE *) Head;\r
57b4ecb9 607 ASSERT(Free != NULL);\r
28a00297 608 Free->Signature = POOL_FREE_SIGNATURE;\r
609 Free->Index = (UINT32)Index;\r
610 InsertHeadList (&Pool->FreeList[Index], &Free->Link);\r
611\r
612 //\r
022c6d45 613 // See if all the pool entries in the same page as Free are freed pool\r
28a00297 614 // entries\r
615 //\r
7970100c 616 NewPage = (CHAR8 *)((UINTN)Free & ~(Granularity - 1));\r
28a00297 617 Free = (POOL_FREE *) &NewPage[0];\r
e94a9ff7 618 ASSERT(Free != NULL);\r
28a00297 619\r
620 if (Free->Signature == POOL_FREE_SIGNATURE) {\r
621\r
28a00297 622 AllFree = TRUE;\r
162ed594 623 Offset = 0;\r
022c6d45 624\r
7970100c 625 while ((Offset < Granularity) && (AllFree)) {\r
7e8e2205
AB
626 Free = (POOL_FREE *) &NewPage[Offset];\r
627 ASSERT(Free != NULL);\r
628 if (Free->Signature != POOL_FREE_SIGNATURE) {\r
629 AllFree = FALSE;\r
28a00297 630 }\r
7e8e2205 631 Offset += LIST_TO_SIZE(Free->Index);\r
28a00297 632 }\r
633\r
634 if (AllFree) {\r
635\r
636 //\r
022c6d45 637 // All of the pool entries in the same page as Free are free pool\r
28a00297 638 // entries\r
639 // Remove all of these pool entries from the free loop lists.\r
640 //\r
641 Free = (POOL_FREE *) &NewPage[0];\r
57b4ecb9 642 ASSERT(Free != NULL);\r
162ed594 643 Offset = 0;\r
022c6d45 644\r
7970100c 645 while (Offset < Granularity) {\r
7e8e2205
AB
646 Free = (POOL_FREE *) &NewPage[Offset];\r
647 ASSERT(Free != NULL);\r
648 RemoveEntryList (&Free->Link);\r
649 Offset += LIST_TO_SIZE(Free->Index);\r
28a00297 650 }\r
651\r
652 //\r
653 // Free the page\r
654 //\r
7970100c 655 CoreFreePoolPages ((EFI_PHYSICAL_ADDRESS) (UINTN)NewPage, EFI_SIZE_TO_PAGES (Granularity));\r
28a00297 656 }\r
657 }\r
658 }\r
659\r
660 //\r
022c6d45 661 // If this is an OS specific memory type, then check to see if the last\r
28a00297 662 // portion of that memory type has been freed. If it has, then free the\r
663 // list entry for that memory type\r
664 //\r
3d78c020 665 if ((INT32)Pool->MemoryType < 0 && Pool->Used == 0) {\r
28a00297 666 RemoveEntryList (&Pool->Link);\r
667 CoreFreePoolI (Pool);\r
668 }\r
669\r
670 return EFI_SUCCESS;\r
671}\r
84edd20b 672\r