MdePkg PeiMemoryAllocationLib: Update Free(Aligned)Pages
[mirror_edk2.git] / MdePkg / Library / PeiMemoryAllocationLib / MemoryAllocationLib.c
CommitLineData
e386b444 1/** @file\r
9e6fa6d2
LG
2 Support routines for memory allocation routines \r
3 based on PeiService for PEI phase drivers.\r
e386b444 4\r
2132ef05 5 Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
19388d29 6 This program and the accompanying materials \r
e386b444 7 are licensed and made available under the terms and conditions of the BSD License \r
8 which accompanies this distribution. The full text of the license may be found at \r
2fc59a00 9 http://opensource.org/licenses/bsd-license.php. \r
e386b444 10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
13\r
e386b444 14**/\r
15\r
c892d846 16\r
c7d265a9 17#include <PiPei.h>\r
c892d846 18\r
19\r
c7d265a9 20#include <Library/MemoryAllocationLib.h>\r
1c280088 21#include <Library/PeiServicesLib.h>\r
c7d265a9 22#include <Library/BaseMemoryLib.h>\r
23#include <Library/DebugLib.h>\r
1dde8b08 24#include <Library/HobLib.h>\r
e386b444 25\r
e386b444 26\r
27/**\r
28 Allocates one or more 4KB pages of a certain memory type.\r
29\r
30 Allocates the number of 4KB pages of a certain memory type and returns a pointer to the allocated\r
31 buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL is returned.\r
32 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
33\r
34 @param MemoryType The type of memory to allocate.\r
35 @param Pages The number of 4 KB pages to allocate.\r
36\r
37 @return A pointer to the allocated buffer or NULL if allocation fails.\r
38\r
39**/\r
40VOID *\r
41InternalAllocatePages (\r
42 IN EFI_MEMORY_TYPE MemoryType, \r
43 IN UINTN Pages\r
44 )\r
45{\r
46 EFI_STATUS Status;\r
47 EFI_PHYSICAL_ADDRESS Memory; \r
e386b444 48\r
49 if (Pages == 0) {\r
50 return NULL;\r
51 }\r
52\r
34363594 53 Status = PeiServicesAllocatePages (MemoryType, Pages, &Memory);\r
e386b444 54 if (EFI_ERROR (Status)) {\r
9e6fa6d2 55 return NULL;\r
e386b444 56 }\r
1dde8b08 57\r
e386b444 58 return (VOID *) (UINTN) Memory;\r
59}\r
60\r
61/**\r
62 Allocates one or more 4KB pages of type EfiBootServicesData.\r
63\r
64 Allocates the number of 4KB pages of type EfiBootServicesData and returns a pointer to the\r
65 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL\r
66 is returned. If there is not enough memory remaining to satisfy the request, then NULL is\r
67 returned.\r
68\r
69 @param Pages The number of 4 KB pages to allocate.\r
70\r
71 @return A pointer to the allocated buffer or NULL if allocation fails.\r
72\r
73**/\r
74VOID *\r
75EFIAPI\r
76AllocatePages (\r
77 IN UINTN Pages\r
78 )\r
79{\r
80 return InternalAllocatePages (EfiBootServicesData, Pages);\r
81}\r
82\r
83/**\r
84 Allocates one or more 4KB pages of type EfiRuntimeServicesData.\r
85\r
86 Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the\r
87 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL\r
88 is returned. If there is not enough memory remaining to satisfy the request, then NULL is\r
89 returned.\r
90\r
91 @param Pages The number of 4 KB pages to allocate.\r
92\r
93 @return A pointer to the allocated buffer or NULL if allocation fails.\r
94\r
95**/\r
96VOID *\r
97EFIAPI\r
98AllocateRuntimePages (\r
99 IN UINTN Pages\r
100 )\r
101{\r
102 return InternalAllocatePages (EfiRuntimeServicesData, Pages);\r
103}\r
104\r
105/**\r
106 Allocates one or more 4KB pages of type EfiReservedMemoryType.\r
107\r
108 Allocates the number of 4KB pages of type EfiReservedMemoryType and returns a pointer to the\r
109 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL\r
110 is returned. If there is not enough memory remaining to satisfy the request, then NULL is\r
111 returned.\r
112\r
113 @param Pages The number of 4 KB pages to allocate.\r
114\r
115 @return A pointer to the allocated buffer or NULL if allocation fails.\r
116\r
117**/\r
118VOID *\r
119EFIAPI\r
120AllocateReservedPages (\r
121 IN UINTN Pages\r
122 )\r
123{\r
124 return InternalAllocatePages (EfiReservedMemoryType, Pages);\r
125}\r
126\r
127/**\r
128 Frees one or more 4KB pages that were previously allocated with one of the page allocation\r
129 functions in the Memory Allocation Library.\r
130\r
131 Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer\r
132 must have been allocated on a previous call to the page allocation services of the Memory\r
6e10b70a 133 Allocation Library. If it is not possible to free allocated pages, then this function will\r
446b94b0 134 perform no actions.\r
9638ba6d 135 \r
e386b444 136 If Buffer was not allocated with a page allocation function in the Memory Allocation Library,\r
137 then ASSERT().\r
138 If Pages is zero, then ASSERT().\r
139 \r
2fc59a00 140 @param Buffer The pointer to the buffer of pages to free.\r
e386b444 141 @param Pages The number of 4 KB pages to free.\r
142\r
143**/\r
144VOID\r
145EFIAPI\r
146FreePages (\r
147 IN VOID *Buffer,\r
148 IN UINTN Pages\r
149 )\r
150{\r
2132ef05
SZ
151 EFI_STATUS Status;\r
152\r
6e10b70a 153 ASSERT (Pages != 0);\r
2132ef05
SZ
154 Status = PeiServicesFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);\r
155 ASSERT_EFI_ERROR (Status);\r
e386b444 156}\r
157\r
158/**\r
159 Allocates one or more 4KB pages of a certain memory type at a specified alignment.\r
160\r
161 Allocates the number of 4KB pages specified by Pages of a certain memory type with an alignment\r
162 specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is returned.\r
163 If there is not enough memory at the specified alignment remaining to satisfy the request, then\r
164 NULL is returned.\r
165 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
1346352d 166 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().\r
e386b444 167\r
168 @param MemoryType The type of memory to allocate.\r
169 @param Pages The number of 4 KB pages to allocate.\r
58380e9c 170 @param Alignment The requested alignment of the allocation. \r
171 Must be a power of two.\r
e386b444 172 If Alignment is zero, then byte alignment is used.\r
173\r
174 @return A pointer to the allocated buffer or NULL if allocation fails.\r
175\r
176**/\r
177VOID *\r
178InternalAllocateAlignedPages (\r
179 IN EFI_MEMORY_TYPE MemoryType, \r
180 IN UINTN Pages,\r
181 IN UINTN Alignment\r
182 )\r
183{\r
6809c872
LG
184 EFI_PHYSICAL_ADDRESS Memory;\r
185 EFI_PHYSICAL_ADDRESS AlignedMemory;\r
186 EFI_PEI_HOB_POINTERS Hob;\r
4c103c55
LG
187 BOOLEAN SkipBeforeMemHob;\r
188 BOOLEAN SkipAfterMemHob;\r
6809c872
LG
189 EFI_PHYSICAL_ADDRESS HobBaseAddress;\r
190 UINT64 HobLength;\r
191 EFI_MEMORY_TYPE HobMemoryType;\r
192 UINTN TotalPages;\r
e386b444 193\r
194 //\r
195 // Alignment must be a power of two or zero.\r
196 //\r
197 ASSERT ((Alignment & (Alignment - 1)) == 0);\r
198\r
199 if (Pages == 0) {\r
200 return NULL;\r
201 }\r
202 //\r
203 // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.\r
204 //\r
6809c872
LG
205 ASSERT (Pages <= (MAX_ADDRESS - EFI_SIZE_TO_PAGES (Alignment))); \r
206\r
e386b444 207 //\r
208 // We would rather waste some memory to save PEI code size.\r
6809c872
LG
209 // meaning in addition to the requested size for the aligned mem,\r
210 // we simply reserve an overhead memory equal to Alignmemt(page-aligned), no matter what.\r
211 // The overhead mem size could be reduced later with more involved malloc mechanisms\r
212 // (e.g., somthing that can detect the alignment boundary before allocating memory or \r
213 // can request that memory be allocated at a certain address that is aleady aligned).\r
214 //\r
215 TotalPages = Pages + (Alignment <= EFI_PAGE_SIZE ? 0 : EFI_SIZE_TO_PAGES(Alignment));\r
216 Memory = (EFI_PHYSICAL_ADDRESS) (UINTN) InternalAllocatePages (MemoryType, TotalPages);\r
217 if (Memory == 0) {\r
218 DEBUG((DEBUG_INFO, "Out of memory resource! \n"));\r
219 return NULL;\r
220 }\r
221 DEBUG ((DEBUG_INFO, "Allocated Memory unaligned: Address = 0x%LX, Pages = 0x%X, Type = %d \n", Memory, TotalPages, (UINTN) MemoryType));\r
222\r
223 //\r
224 // Alignment calculation\r
225 //\r
226 AlignedMemory = Memory;\r
227 if (Alignment > EFI_PAGE_SIZE) {\r
228 AlignedMemory = ALIGN_VALUE (Memory, Alignment);\r
229 }\r
230 DEBUG ((DEBUG_INFO, "After aligning to 0x%X bytes: Address = 0x%LX, Pages = 0x%X \n", Alignment, AlignedMemory, Pages));\r
231\r
232 //\r
233 // In general three HOBs cover the total allocated space.\r
234 // The aligned portion is covered by the aligned mem HOB and\r
235 // the unaligned(to be freed) portions before and after the aligned portion are covered by newly created HOBs.\r
e386b444 236 //\r
6809c872
LG
237 // Before mem HOB covers the region between "Memory" and "AlignedMemory"\r
238 // Aligned mem HOB covers the region between "AlignedMemory" and "AlignedMemory + EFI_PAGES_TO_SIZE(Pages)"\r
239 // After mem HOB covers the region between "AlignedMemory + EFI_PAGES_TO_SIZE(Pages)" and "Memory + EFI_PAGES_TO_SIZE(TotalPages)"\r
240 //\r
241 // The before or after mem HOBs need to be skipped under special cases where the aligned portion\r
242 // touches either the top or bottom of the original allocated space.\r
243 //\r
4c103c55
LG
244 SkipBeforeMemHob = FALSE;\r
245 SkipAfterMemHob = FALSE;\r
6809c872
LG
246 if (Memory == AlignedMemory) {\r
247 SkipBeforeMemHob = TRUE;\r
248 }\r
249 if ((Memory + EFI_PAGES_TO_SIZE(TotalPages)) == (AlignedMemory + EFI_PAGES_TO_SIZE(Pages))) {\r
250 //\r
251 // This condition is never met in the current implementation.\r
252 // There is always some after-mem since the overhead mem(used in TotalPages)\r
253 // is no less than Alignment.\r
254 //\r
255 SkipAfterMemHob = TRUE;\r
256 }\r
257\r
258 // \r
259 // Search for the mem HOB referring to the original(unaligned) allocation \r
260 // and update the size and type if needed.\r
261 //\r
262 Hob.Raw = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION);\r
263 while (Hob.Raw != NULL) {\r
264 if (Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress == Memory) {\r
265 break;\r
266 }\r
267 Hob.Raw = GET_NEXT_HOB (Hob);\r
268 Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw);\r
269 }\r
270 ASSERT (Hob.Raw != NULL);\r
271 if (SkipBeforeMemHob) {\r
272 //\r
273 // Use this HOB as aligned mem HOB as there is no portion before it.\r
274 //\r
275 HobLength = EFI_PAGES_TO_SIZE(Pages);\r
276 Hob.MemoryAllocation->AllocDescriptor.MemoryLength = HobLength;\r
277 } else {\r
278 //\r
279 // Use this HOB as before mem HOB and create a new HOB for the aligned portion \r
280 //\r
281 HobLength = (AlignedMemory - Memory); \r
282 Hob.MemoryAllocation->AllocDescriptor.MemoryLength = HobLength;\r
283 Hob.MemoryAllocation->AllocDescriptor.MemoryType = EfiConventionalMemory;\r
284 }\r
285\r
286 HobBaseAddress = Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress;\r
287 HobMemoryType = Hob.MemoryAllocation->AllocDescriptor.MemoryType;\r
288\r
289 //\r
290 // Build the aligned mem HOB if needed\r
291 //\r
292 if (!SkipBeforeMemHob) {\r
293 DEBUG((DEBUG_INFO, "Updated before-mem HOB with BaseAddress = %LX, Length = %LX, MemoryType = %d \n",\r
294 HobBaseAddress, HobLength, (UINTN) HobMemoryType));\r
295\r
296 HobBaseAddress = AlignedMemory;\r
297 HobLength = EFI_PAGES_TO_SIZE(Pages);\r
298 HobMemoryType = MemoryType;\r
299\r
300 BuildMemoryAllocationHob (\r
301 HobBaseAddress,\r
302 HobLength,\r
303 HobMemoryType\r
304 );\r
305\r
306 DEBUG((DEBUG_INFO, "Created aligned-mem HOB with BaseAddress = %LX, Length = %LX, MemoryType = %d \n",\r
307 HobBaseAddress, HobLength, (UINTN) HobMemoryType));\r
e386b444 308 } else {\r
6809c872
LG
309 if (HobBaseAddress != 0) {\r
310 DEBUG((DEBUG_INFO, "Updated aligned-mem HOB with BaseAddress = %LX, Length = %LX, MemoryType = %d \n",\r
311 HobBaseAddress, HobLength, (UINTN) HobMemoryType));\r
312 }\r
e386b444 313 }\r
6809c872
LG
314\r
315\r
316 //\r
317 // Build the after mem HOB if needed\r
318 //\r
319 if (!SkipAfterMemHob) {\r
320 HobBaseAddress = AlignedMemory + EFI_PAGES_TO_SIZE(Pages);\r
321 HobLength = (Memory + EFI_PAGES_TO_SIZE(TotalPages)) - (AlignedMemory + EFI_PAGES_TO_SIZE(Pages));\r
322 HobMemoryType = EfiConventionalMemory;\r
323\r
324 BuildMemoryAllocationHob (\r
325 HobBaseAddress,\r
326 HobLength,\r
327 HobMemoryType\r
328 );\r
329\r
330 DEBUG((DEBUG_INFO, "Created after-mem HOB with BaseAddress = %LX, Length = %LX, MemoryType = %d \n",\r
331 HobBaseAddress, HobLength, (UINTN) HobMemoryType));\r
332 }\r
333\r
334 return (VOID *) (UINTN) AlignedMemory;\r
e386b444 335}\r
336\r
337/**\r
338 Allocates one or more 4KB pages of type EfiBootServicesData at a specified alignment.\r
339\r
340 Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData with an\r
341 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is\r
342 returned. If there is not enough memory at the specified alignment remaining to satisfy the\r
343 request, then NULL is returned.\r
9638ba6d 344 \r
e386b444 345 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
1346352d 346 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().\r
e386b444 347\r
348 @param Pages The number of 4 KB pages to allocate.\r
58380e9c 349 @param Alignment The requested alignment of the allocation. \r
350 Must be a power of two.\r
e386b444 351 If Alignment is zero, then byte alignment is used.\r
352\r
353 @return A pointer to the allocated buffer or NULL if allocation fails.\r
354\r
355**/\r
356VOID *\r
357EFIAPI\r
358AllocateAlignedPages (\r
359 IN UINTN Pages,\r
360 IN UINTN Alignment\r
361 )\r
362{\r
363 return InternalAllocateAlignedPages (EfiBootServicesData, Pages, Alignment);\r
364}\r
365\r
366/**\r
367 Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment.\r
368\r
369 Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData with an\r
370 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is\r
371 returned. If there is not enough memory at the specified alignment remaining to satisfy the\r
372 request, then NULL is returned.\r
9638ba6d 373 \r
e386b444 374 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
1346352d 375 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().\r
e386b444 376\r
377 @param Pages The number of 4 KB pages to allocate.\r
58380e9c 378 @param Alignment The requested alignment of the allocation. \r
379 Must be a power of two.\r
e386b444 380 If Alignment is zero, then byte alignment is used.\r
381\r
382 @return A pointer to the allocated buffer or NULL if allocation fails.\r
383\r
384**/\r
385VOID *\r
386EFIAPI\r
387AllocateAlignedRuntimePages (\r
388 IN UINTN Pages,\r
389 IN UINTN Alignment\r
390 )\r
391{\r
392 return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment);\r
393}\r
394\r
395/**\r
396 Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment.\r
397\r
398 Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType with an\r
399 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is\r
400 returned. If there is not enough memory at the specified alignment remaining to satisfy the\r
401 request, then NULL is returned.\r
9638ba6d 402 \r
e386b444 403 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
1346352d 404 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().\r
e386b444 405\r
406 @param Pages The number of 4 KB pages to allocate.\r
58380e9c 407 @param Alignment The requested alignment of the allocation. \r
408 Must be a power of two.\r
e386b444 409 If Alignment is zero, then byte alignment is used.\r
410\r
411 @return A pointer to the allocated buffer or NULL if allocation fails.\r
412\r
413**/\r
414VOID *\r
415EFIAPI\r
416AllocateAlignedReservedPages (\r
417 IN UINTN Pages,\r
418 IN UINTN Alignment\r
419 )\r
420{\r
421 return InternalAllocateAlignedPages (EfiReservedMemoryType, Pages, Alignment);\r
422}\r
423\r
424/**\r
425 Frees one or more 4KB pages that were previously allocated with one of the aligned page\r
426 allocation functions in the Memory Allocation Library.\r
427\r
428 Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer\r
429 must have been allocated on a previous call to the aligned page allocation services of the Memory\r
6e10b70a 430 Allocation Library. If it is not possible to free allocated pages, then this function will \r
446b94b0 431 perform no actions.\r
9638ba6d 432 \r
e386b444 433 If Buffer was not allocated with an aligned page allocation function in the Memory Allocation\r
434 Library, then ASSERT().\r
435 If Pages is zero, then ASSERT().\r
436 \r
2fc59a00 437 @param Buffer The pointer to the buffer of pages to free.\r
e386b444 438 @param Pages The number of 4 KB pages to free.\r
439\r
440**/\r
441VOID\r
442EFIAPI\r
443FreeAlignedPages (\r
444 IN VOID *Buffer,\r
445 IN UINTN Pages\r
446 )\r
447{\r
2132ef05
SZ
448 EFI_STATUS Status;\r
449\r
6e10b70a 450 ASSERT (Pages != 0);\r
2132ef05
SZ
451 Status = PeiServicesFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);\r
452 ASSERT_EFI_ERROR (Status);\r
e386b444 453}\r
454\r
455/**\r
456 Allocates a buffer of a certain pool type.\r
457\r
458 Allocates the number bytes specified by AllocationSize of a certain pool type and returns a\r
459 pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is\r
460 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
461\r
462 @param MemoryType The type of memory to allocate.\r
463 @param AllocationSize The number of bytes to allocate.\r
464\r
465 @return A pointer to the allocated buffer or NULL if allocation fails.\r
466\r
467**/\r
468VOID *\r
469InternalAllocatePool (\r
470 IN EFI_MEMORY_TYPE MemoryType, \r
471 IN UINTN AllocationSize\r
472 )\r
473{\r
474 //\r
475 // If we need lots of small runtime/reserved memory type from PEI in the future, \r
476 // we can consider providing a more complex algorithm that allocates runtime pages and \r
477 // provide pool allocations from those pages. \r
478 //\r
479 return InternalAllocatePages (MemoryType, EFI_SIZE_TO_PAGES (AllocationSize));\r
480}\r
481\r
482/**\r
483 Allocates a buffer of type EfiBootServicesData.\r
484\r
485 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a\r
486 pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is\r
487 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
488\r
489 @param AllocationSize The number of bytes to allocate.\r
490\r
491 @return A pointer to the allocated buffer or NULL if allocation fails.\r
492\r
493**/\r
494VOID *\r
495EFIAPI\r
496AllocatePool (\r
497 IN UINTN AllocationSize\r
498 )\r
499{\r
500 EFI_STATUS Status;\r
e386b444 501 VOID *Buffer;\r
502 \r
1c280088 503 Status = PeiServicesAllocatePool (AllocationSize, &Buffer);\r
e386b444 504 if (EFI_ERROR (Status)) {\r
505 Buffer = NULL;\r
506 }\r
507 return Buffer;\r
508}\r
509\r
510/**\r
511 Allocates a buffer of type EfiRuntimeServicesData.\r
512\r
513 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData and returns\r
514 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is\r
515 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
516\r
517 @param AllocationSize The number of bytes to allocate.\r
518\r
519 @return A pointer to the allocated buffer or NULL if allocation fails.\r
520\r
521**/\r
522VOID *\r
523EFIAPI\r
524AllocateRuntimePool (\r
525 IN UINTN AllocationSize\r
526 )\r
527{\r
528 return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize);\r
529}\r
530\r
531/**\r
8789c5e0 532 Allocates a buffer of type EfiReservedMemoryType.\r
e386b444 533\r
8789c5e0 534 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType and returns\r
e386b444 535 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is\r
536 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
537\r
538 @param AllocationSize The number of bytes to allocate.\r
539\r
540 @return A pointer to the allocated buffer or NULL if allocation fails.\r
541\r
542**/\r
543VOID *\r
544EFIAPI\r
545AllocateReservedPool (\r
546 IN UINTN AllocationSize\r
547 )\r
548{\r
549 return InternalAllocatePool (EfiReservedMemoryType, AllocationSize);\r
550}\r
551\r
552/**\r
446b94b0 553 Allocates and zeros a buffer of a certain pool type.\r
e386b444 554\r
446b94b0 555 Allocates the number bytes specified by AllocationSize of a certain pool type, clears the buffer\r
e386b444 556 with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a valid\r
557 buffer of 0 size is returned. If there is not enough memory remaining to satisfy the request,\r
558 then NULL is returned.\r
559\r
560 @param PoolType The type of memory to allocate.\r
561 @param AllocationSize The number of bytes to allocate and zero.\r
562\r
563 @return A pointer to the allocated buffer or NULL if allocation fails.\r
564\r
565**/\r
566VOID *\r
567InternalAllocateZeroPool (\r
568 IN EFI_MEMORY_TYPE PoolType, \r
569 IN UINTN AllocationSize\r
570 ) \r
571{\r
572 VOID *Memory;\r
573\r
574 Memory = InternalAllocatePool (PoolType, AllocationSize);\r
575 if (Memory != NULL) {\r
576 Memory = ZeroMem (Memory, AllocationSize);\r
577 }\r
578 return Memory;\r
579}\r
580\r
581/**\r
582 Allocates and zeros a buffer of type EfiBootServicesData.\r
583\r
584 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the\r
585 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a\r
586 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the\r
587 request, then NULL is returned.\r
588\r
589 @param AllocationSize The number of bytes to allocate and zero.\r
590\r
591 @return A pointer to the allocated buffer or NULL if allocation fails.\r
592\r
593**/\r
594VOID *\r
595EFIAPI\r
596AllocateZeroPool (\r
597 IN UINTN AllocationSize\r
598 )\r
599{\r
600 VOID *Memory;\r
601\r
602 Memory = AllocatePool (AllocationSize);\r
603 if (Memory != NULL) {\r
604 Memory = ZeroMem (Memory, AllocationSize);\r
605 }\r
606 return Memory;\r
607}\r
608\r
609/**\r
610 Allocates and zeros a buffer of type EfiRuntimeServicesData.\r
611\r
612 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, clears the\r
613 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a\r
614 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the\r
615 request, then NULL is returned.\r
616\r
617 @param AllocationSize The number of bytes to allocate and zero.\r
618\r
619 @return A pointer to the allocated buffer or NULL if allocation fails.\r
620\r
621**/\r
622VOID *\r
623EFIAPI\r
624AllocateRuntimeZeroPool (\r
625 IN UINTN AllocationSize\r
626 )\r
627{\r
628 return InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize);\r
629}\r
630\r
631/**\r
632 Allocates and zeros a buffer of type EfiReservedMemoryType.\r
633\r
634 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, clears the\r
635 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a\r
636 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the\r
637 request, then NULL is returned.\r
638\r
639 @param AllocationSize The number of bytes to allocate and zero.\r
640\r
641 @return A pointer to the allocated buffer or NULL if allocation fails.\r
642\r
643**/\r
644VOID *\r
645EFIAPI\r
646AllocateReservedZeroPool (\r
647 IN UINTN AllocationSize\r
648 )\r
649{\r
650 return InternalAllocateZeroPool (EfiReservedMemoryType, AllocationSize);\r
651}\r
652\r
653/**\r
446b94b0 654 Copies a buffer to an allocated buffer of a certain pool type.\r
e386b444 655\r
446b94b0 656 Allocates the number bytes specified by AllocationSize of a certain pool type, copies\r
e386b444 657 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the\r
658 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there\r
659 is not enough memory remaining to satisfy the request, then NULL is returned.\r
660 If Buffer is NULL, then ASSERT().\r
9e6fa6d2 661 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). \r
e386b444 662\r
663 @param PoolType The type of pool to allocate.\r
664 @param AllocationSize The number of bytes to allocate and zero.\r
665 @param Buffer The buffer to copy to the allocated buffer.\r
666\r
667 @return A pointer to the allocated buffer or NULL if allocation fails.\r
668\r
669**/\r
670VOID *\r
671InternalAllocateCopyPool (\r
672 IN EFI_MEMORY_TYPE PoolType, \r
673 IN UINTN AllocationSize,\r
674 IN CONST VOID *Buffer\r
675 ) \r
676{\r
677 VOID *Memory;\r
678\r
679 ASSERT (Buffer != NULL);\r
680 ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1));\r
681\r
682 Memory = InternalAllocatePool (PoolType, AllocationSize);\r
683 if (Memory != NULL) {\r
684 Memory = CopyMem (Memory, Buffer, AllocationSize);\r
685 }\r
686 return Memory;\r
687} \r
688\r
689/**\r
690 Copies a buffer to an allocated buffer of type EfiBootServicesData.\r
691\r
692 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, copies\r
693 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the\r
694 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there\r
695 is not enough memory remaining to satisfy the request, then NULL is returned.\r
9638ba6d 696 \r
e386b444 697 If Buffer is NULL, then ASSERT().\r
9e6fa6d2 698 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). \r
e386b444 699\r
700 @param AllocationSize The number of bytes to allocate and zero.\r
701 @param Buffer The buffer to copy to the allocated buffer.\r
702\r
703 @return A pointer to the allocated buffer or NULL if allocation fails.\r
704\r
705**/\r
706VOID *\r
707EFIAPI\r
708AllocateCopyPool (\r
709 IN UINTN AllocationSize,\r
710 IN CONST VOID *Buffer\r
711 )\r
712{\r
713 VOID *Memory;\r
714\r
715 ASSERT (Buffer != NULL);\r
716 ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1));\r
717\r
718 Memory = AllocatePool (AllocationSize);\r
719 if (Memory != NULL) {\r
720 Memory = CopyMem (Memory, Buffer, AllocationSize);\r
721 }\r
722 return Memory;\r
723}\r
724\r
725/**\r
726 Copies a buffer to an allocated buffer of type EfiRuntimeServicesData.\r
727\r
728 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, copies\r
729 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the\r
730 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there\r
731 is not enough memory remaining to satisfy the request, then NULL is returned.\r
9638ba6d 732 \r
e386b444 733 If Buffer is NULL, then ASSERT().\r
9e6fa6d2 734 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). \r
e386b444 735\r
736 @param AllocationSize The number of bytes to allocate and zero.\r
737 @param Buffer The buffer to copy to the allocated buffer.\r
738\r
739 @return A pointer to the allocated buffer or NULL if allocation fails.\r
740\r
741**/\r
742VOID *\r
743EFIAPI\r
744AllocateRuntimeCopyPool (\r
745 IN UINTN AllocationSize,\r
746 IN CONST VOID *Buffer\r
747 )\r
748{\r
749 return InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer);\r
750}\r
751\r
752/**\r
753 Copies a buffer to an allocated buffer of type EfiReservedMemoryType.\r
754\r
755 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, copies\r
756 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the\r
757 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there\r
758 is not enough memory remaining to satisfy the request, then NULL is returned.\r
9638ba6d 759 \r
e386b444 760 If Buffer is NULL, then ASSERT().\r
9e6fa6d2 761 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). \r
e386b444 762\r
763 @param AllocationSize The number of bytes to allocate and zero.\r
764 @param Buffer The buffer to copy to the allocated buffer.\r
765\r
766 @return A pointer to the allocated buffer or NULL if allocation fails.\r
767\r
768**/\r
769VOID *\r
770EFIAPI\r
771AllocateReservedCopyPool (\r
772 IN UINTN AllocationSize,\r
773 IN CONST VOID *Buffer\r
774 )\r
775{\r
776 return InternalAllocateCopyPool (EfiReservedMemoryType, AllocationSize, Buffer);\r
777}\r
778\r
3b6a71fc 779/**\r
780 Reallocates a buffer of a specified memory type.\r
781\r
782 Allocates and zeros the number bytes specified by NewSize from memory of the type\r
783 specified by PoolType. If OldBuffer is not NULL, then the smaller of OldSize and \r
784 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and \r
785 OldBuffer is freed. A pointer to the newly allocated buffer is returned. \r
786 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not \r
787 enough memory remaining to satisfy the request, then NULL is returned.\r
788 \r
56304569 789 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize\r
790 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().\r
3b6a71fc 791\r
792 @param PoolType The type of pool to allocate.\r
793 @param OldSize The size, in bytes, of OldBuffer.\r
794 @param NewSize The size, in bytes, of the buffer to reallocate.\r
58380e9c 795 @param OldBuffer The buffer to copy to the allocated buffer. This is an \r
796 optional parameter that may be NULL.\r
3b6a71fc 797\r
798 @return A pointer to the allocated buffer or NULL if allocation fails.\r
799\r
800**/\r
801VOID *\r
3b6a71fc 802InternalReallocatePool (\r
803 IN EFI_MEMORY_TYPE PoolType, \r
804 IN UINTN OldSize,\r
805 IN UINTN NewSize,\r
806 IN VOID *OldBuffer OPTIONAL\r
807 )\r
808{\r
809 VOID *NewBuffer;\r
810\r
6babbe1f 811 NewBuffer = InternalAllocateZeroPool (PoolType, NewSize);\r
3b6a71fc 812 if (NewBuffer != NULL && OldBuffer != NULL) {\r
813 CopyMem (NewBuffer, OldBuffer, MIN (OldSize, NewSize));\r
814 FreePool (OldBuffer);\r
815 }\r
816 return NewBuffer;\r
817}\r
818\r
819/**\r
820 Reallocates a buffer of type EfiBootServicesData.\r
821\r
822 Allocates and zeros the number bytes specified by NewSize from memory of type\r
823 EfiBootServicesData. If OldBuffer is not NULL, then the smaller of OldSize and \r
824 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and \r
825 OldBuffer is freed. A pointer to the newly allocated buffer is returned. \r
826 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not \r
827 enough memory remaining to satisfy the request, then NULL is returned.\r
828 \r
56304569 829 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize\r
830 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().\r
3b6a71fc 831\r
832 @param OldSize The size, in bytes, of OldBuffer.\r
833 @param NewSize The size, in bytes, of the buffer to reallocate.\r
834 @param OldBuffer The buffer to copy to the allocated buffer. This is an optional \r
835 parameter that may be NULL.\r
836\r
837 @return A pointer to the allocated buffer or NULL if allocation fails.\r
838\r
839**/\r
840VOID *\r
841EFIAPI\r
842ReallocatePool (\r
843 IN UINTN OldSize,\r
844 IN UINTN NewSize,\r
845 IN VOID *OldBuffer OPTIONAL\r
846 )\r
847{\r
848 return InternalReallocatePool (EfiBootServicesData, OldSize, NewSize, OldBuffer);\r
849}\r
850\r
851/**\r
852 Reallocates a buffer of type EfiRuntimeServicesData.\r
853\r
854 Allocates and zeros the number bytes specified by NewSize from memory of type\r
855 EfiRuntimeServicesData. If OldBuffer is not NULL, then the smaller of OldSize and \r
856 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and \r
857 OldBuffer is freed. A pointer to the newly allocated buffer is returned. \r
858 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not \r
859 enough memory remaining to satisfy the request, then NULL is returned.\r
860\r
56304569 861 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize\r
862 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().\r
3b6a71fc 863\r
864 @param OldSize The size, in bytes, of OldBuffer.\r
865 @param NewSize The size, in bytes, of the buffer to reallocate.\r
866 @param OldBuffer The buffer to copy to the allocated buffer. This is an optional \r
867 parameter that may be NULL.\r
868\r
869 @return A pointer to the allocated buffer or NULL if allocation fails.\r
870\r
871**/\r
872VOID *\r
873EFIAPI\r
874ReallocateRuntimePool (\r
875 IN UINTN OldSize,\r
876 IN UINTN NewSize,\r
877 IN VOID *OldBuffer OPTIONAL\r
878 )\r
879{\r
880 return InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer);\r
881}\r
882\r
883/**\r
884 Reallocates a buffer of type EfiReservedMemoryType.\r
885\r
886 Allocates and zeros the number bytes specified by NewSize from memory of type\r
887 EfiReservedMemoryType. If OldBuffer is not NULL, then the smaller of OldSize and \r
888 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and \r
889 OldBuffer is freed. A pointer to the newly allocated buffer is returned. \r
890 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not \r
891 enough memory remaining to satisfy the request, then NULL is returned.\r
2297186d 892\r
56304569 893 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize\r
894 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().\r
3b6a71fc 895\r
896 @param OldSize The size, in bytes, of OldBuffer.\r
897 @param NewSize The size, in bytes, of the buffer to reallocate.\r
58380e9c 898 @param OldBuffer The buffer to copy to the allocated buffer. This is an \r
899 optional parameter that may be NULL.\r
3b6a71fc 900\r
901 @return A pointer to the allocated buffer or NULL if allocation fails.\r
902\r
903**/\r
904VOID *\r
905EFIAPI\r
906ReallocateReservedPool (\r
907 IN UINTN OldSize,\r
908 IN UINTN NewSize,\r
909 IN VOID *OldBuffer OPTIONAL\r
910 )\r
911{\r
912 return InternalReallocatePool (EfiReservedMemoryType, OldSize, NewSize, OldBuffer);\r
913}\r
914\r
e386b444 915/**\r
916 Frees a buffer that was previously allocated with one of the pool allocation functions in the\r
917 Memory Allocation Library.\r
918\r
919 Frees the buffer specified by Buffer. Buffer must have been allocated on a previous call to the\r
6e10b70a 920 pool allocation services of the Memory Allocation Library. If it is not possible to free pool\r
446b94b0 921 resources, then this function will perform no actions.\r
9638ba6d 922 \r
e386b444 923 If Buffer was not allocated with a pool allocation function in the Memory Allocation Library,\r
924 then ASSERT().\r
925\r
2fc59a00 926 @param Buffer The pointer to the buffer to free.\r
e386b444 927\r
928**/\r
929VOID\r
930EFIAPI\r
931FreePool (\r
932 IN VOID *Buffer\r
933 )\r
934{\r
935 //\r
936 // PEI phase does not support to free pool, so leave it as NOP.\r
937 //\r
938}\r
939\r
7d582d6b 940\r