]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdePkg/Library/PeiMemoryAllocationLib/MemoryAllocationLib.c
MdePkg PeiMemoryAllocationLib: Update Free(Aligned)Pages
[mirror_edk2.git] / MdePkg / Library / PeiMemoryAllocationLib / MemoryAllocationLib.c
... / ...
CommitLineData
1/** @file\r
2 Support routines for memory allocation routines \r
3 based on PeiService for PEI phase drivers.\r
4\r
5 Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
6 This program and the accompanying materials \r
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
9 http://opensource.org/licenses/bsd-license.php. \r
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
14**/\r
15\r
16\r
17#include <PiPei.h>\r
18\r
19\r
20#include <Library/MemoryAllocationLib.h>\r
21#include <Library/PeiServicesLib.h>\r
22#include <Library/BaseMemoryLib.h>\r
23#include <Library/DebugLib.h>\r
24#include <Library/HobLib.h>\r
25\r
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
48\r
49 if (Pages == 0) {\r
50 return NULL;\r
51 }\r
52\r
53 Status = PeiServicesAllocatePages (MemoryType, Pages, &Memory);\r
54 if (EFI_ERROR (Status)) {\r
55 return NULL;\r
56 }\r
57\r
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
133 Allocation Library. If it is not possible to free allocated pages, then this function will\r
134 perform no actions.\r
135 \r
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
140 @param Buffer The pointer to the buffer of pages to free.\r
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
151 EFI_STATUS Status;\r
152\r
153 ASSERT (Pages != 0);\r
154 Status = PeiServicesFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);\r
155 ASSERT_EFI_ERROR (Status);\r
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
166 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().\r
167\r
168 @param MemoryType The type of memory to allocate.\r
169 @param Pages The number of 4 KB pages to allocate.\r
170 @param Alignment The requested alignment of the allocation. \r
171 Must be a power of two.\r
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
184 EFI_PHYSICAL_ADDRESS Memory;\r
185 EFI_PHYSICAL_ADDRESS AlignedMemory;\r
186 EFI_PEI_HOB_POINTERS Hob;\r
187 BOOLEAN SkipBeforeMemHob;\r
188 BOOLEAN SkipAfterMemHob;\r
189 EFI_PHYSICAL_ADDRESS HobBaseAddress;\r
190 UINT64 HobLength;\r
191 EFI_MEMORY_TYPE HobMemoryType;\r
192 UINTN TotalPages;\r
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
205 ASSERT (Pages <= (MAX_ADDRESS - EFI_SIZE_TO_PAGES (Alignment))); \r
206\r
207 //\r
208 // We would rather waste some memory to save PEI code size.\r
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
236 //\r
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
244 SkipBeforeMemHob = FALSE;\r
245 SkipAfterMemHob = FALSE;\r
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
308 } else {\r
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
313 }\r
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
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
344 \r
345 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
346 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().\r
347\r
348 @param Pages The number of 4 KB pages to allocate.\r
349 @param Alignment The requested alignment of the allocation. \r
350 Must be a power of two.\r
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
373 \r
374 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
375 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().\r
376\r
377 @param Pages The number of 4 KB pages to allocate.\r
378 @param Alignment The requested alignment of the allocation. \r
379 Must be a power of two.\r
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
402 \r
403 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
404 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().\r
405\r
406 @param Pages The number of 4 KB pages to allocate.\r
407 @param Alignment The requested alignment of the allocation. \r
408 Must be a power of two.\r
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
430 Allocation Library. If it is not possible to free allocated pages, then this function will \r
431 perform no actions.\r
432 \r
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
437 @param Buffer The pointer to the buffer of pages to free.\r
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
448 EFI_STATUS Status;\r
449\r
450 ASSERT (Pages != 0);\r
451 Status = PeiServicesFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);\r
452 ASSERT_EFI_ERROR (Status);\r
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
501 VOID *Buffer;\r
502 \r
503 Status = PeiServicesAllocatePool (AllocationSize, &Buffer);\r
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
532 Allocates a buffer of type EfiReservedMemoryType.\r
533\r
534 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType and returns\r
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
553 Allocates and zeros a buffer of a certain pool type.\r
554\r
555 Allocates the number bytes specified by AllocationSize of a certain pool type, clears the buffer\r
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
654 Copies a buffer to an allocated buffer of a certain pool type.\r
655\r
656 Allocates the number bytes specified by AllocationSize of a certain pool type, copies\r
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
661 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). \r
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
696 \r
697 If Buffer is NULL, then ASSERT().\r
698 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). \r
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
732 \r
733 If Buffer is NULL, then ASSERT().\r
734 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). \r
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
759 \r
760 If Buffer is NULL, then ASSERT().\r
761 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). \r
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
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
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
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
795 @param OldBuffer The buffer to copy to the allocated buffer. This is an \r
796 optional parameter that may be NULL.\r
797\r
798 @return A pointer to the allocated buffer or NULL if allocation fails.\r
799\r
800**/\r
801VOID *\r
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
811 NewBuffer = InternalAllocateZeroPool (PoolType, NewSize);\r
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
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
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
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
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
892\r
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
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
898 @param OldBuffer The buffer to copy to the allocated buffer. This is an \r
899 optional parameter that may be NULL.\r
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
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
920 pool allocation services of the Memory Allocation Library. If it is not possible to free pool\r
921 resources, then this function will perform no actions.\r
922 \r
923 If Buffer was not allocated with a pool allocation function in the Memory Allocation Library,\r
924 then ASSERT().\r
925\r
926 @param Buffer The pointer to the buffer to free.\r
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
940\r