]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/DxeMemoryAllocationLib/MemoryAllocationLib.c
MemoryAllocationLib: For boundary case: “AllocationSize + OverAllocationSize >= 4G”
[mirror_edk2.git] / MdePkg / Library / DxeMemoryAllocationLib / MemoryAllocationLib.c
CommitLineData
878ddf1f 1/** @file\r
2 Support routines for memory allocation routines for use with drivers.\r
3\r
4 Copyright (c) 2006, Intel Corporation<BR>\r
5 All rights reserved. This program and the accompanying materials \r
6 are licensed and made available under the terms and conditions of the BSD License \r
7 which accompanies this distribution. The full text of the license may be found at \r
8 http://opensource.org/licenses/bsd-license.php \r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
12\r
13 Module Name: MemoryAllocationLib.c\r
14\r
15**/\r
16\r
17\r
18\r
19/**\r
20 Allocates the number of 4KB pages specified by Pages of a certain memory type.\r
21\r
22 @param MemoryType The type of memory to allocate.\r
23 @param Pages The number of 4 KB pages to allocate.\r
24\r
25 @return A pointer to the allocated buffer. The buffer returned is aligned on a 4KB boundary.<BR>\r
26 If Pages is 0, then NULL is returned.<BR>\r
27 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
28\r
29**/\r
30VOID *\r
31InternalAllocatePages (\r
32 IN EFI_MEMORY_TYPE MemoryType, \r
33 IN UINTN Pages\r
34 )\r
35{\r
36 EFI_STATUS Status;\r
37 EFI_PHYSICAL_ADDRESS Memory; \r
38\r
39 if (Pages == 0) {\r
40 return NULL;\r
41 }\r
42\r
43 Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory);\r
44 if (EFI_ERROR (Status)) {\r
45 Memory = 0;\r
46 }\r
47 return (VOID *) (UINTN) Memory;\r
48}\r
49\r
50/**\r
51 Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData.\r
52\r
53 @param Pages The number of 4 KB pages to allocate.\r
54\r
55 @return A pointer to the allocated buffer. The buffer returned is aligned on a 4KB boundary.<BR>\r
56 If Pages is 0, then NULL is returned.<BR>\r
57 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
58\r
59**/\r
60VOID *\r
61EFIAPI\r
62AllocatePages (\r
63 IN UINTN Pages\r
64 )\r
65{\r
66 return InternalAllocatePages (EfiBootServicesData, Pages);\r
67}\r
68\r
69/**\r
70 Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData. \r
71\r
72 @param Pages The number of 4 KB pages to allocate.\r
73\r
74 @return A pointer to the allocated buffer. The buffer returned is aligned on a 4KB boundary.<BR>\r
75 If Pages is 0, then NULL is returned.<BR>\r
76 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
77\r
78**/\r
79VOID *\r
80EFIAPI\r
81AllocateRuntimePages (\r
82 IN UINTN Pages\r
83 )\r
84{\r
85 return InternalAllocatePages (EfiRuntimeServicesData, Pages);\r
86}\r
87\r
88/**\r
89 Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType. \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. The buffer returned is aligned on a 4KB boundary.<BR>\r
94 If Pages is 0, then NULL is returned.<BR>\r
95 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
96\r
97**/\r
98VOID *\r
99EFIAPI\r
100AllocateReservedPages (\r
101 IN UINTN Pages\r
102 )\r
103{\r
104 return InternalAllocatePages (EfiReservedMemoryType, Pages);\r
105}\r
106\r
107/**\r
108 Frees one or more 4KB pages that were previously allocated with \r
109 one of the page allocation functions in the Memory Allocation Library.\r
110\r
111 @param Buffer Pointer to the buffer of pages to free.\r
112 @param Pages The number of 4 KB pages to free.\r
113\r
114**/\r
115VOID\r
116EFIAPI\r
117FreePages (\r
118 IN VOID *Buffer,\r
119 IN UINTN Pages\r
120 )\r
121{\r
122 EFI_STATUS Status;\r
123\r
124 ASSERT (Pages != 0);\r
125 Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);\r
126 ASSERT_EFI_ERROR (Status);\r
127}\r
128\r
129/**\r
130 Allocates the number of 4KB pages specified by Pages of a certian memory type \r
131 with an alignment specified by Alignment. \r
132\r
133 @param MemoryType The type of memory to allocate.\r
134 @param Pages The number of 4 KB pages to allocate.\r
135 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
136 If Alignment is zero, then byte alignment is used.\r
137\r
138 @return The allocated buffer is returned.<BR>\r
139 If Pages is 0, then NULL is returned.<BR>\r
140 If there is not enough memory at the specified alignment remaining to satisfy the request, then NULL is returned.\r
141\r
142**/\r
143VOID *\r
144InternalAllocateAlignedPages (\r
145 IN EFI_MEMORY_TYPE MemoryType, \r
146 IN UINTN Pages,\r
147 IN UINTN Alignment\r
148 )\r
149{\r
150 EFI_STATUS Status;\r
151 EFI_PHYSICAL_ADDRESS Memory;\r
152 UINTN AlignedMemory;\r
153 UINTN AlignmentMask;\r
154 UINTN UnalignedPages;\r
155 UINTN RealPages;\r
156\r
157 //\r
158 // Alignment must be a power of two or zero.\r
159 //\r
160 ASSERT ((Alignment & (Alignment - 1)) == 0);\r
161 \r
162 if (Pages == 0) {\r
163 return NULL;\r
164 }\r
165 if (Alignment > EFI_PAGE_SIZE) {\r
166 //\r
167 // Caculate the total number of pages since alignment is larger than page size.\r
168 //\r
169 AlignmentMask = Alignment - 1;\r
170 RealPages = Pages + EFI_SIZE_TO_PAGES (Alignment);\r
a3657e3e 171 //\r
172 // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.\r
173 //\r
174 ASSERT (RealPages > Pages);\r
175 \r
878ddf1f 176 Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, RealPages, &Memory);\r
177 if (EFI_ERROR (Status)) {\r
178 return NULL;\r
179 }\r
180 AlignedMemory = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask;\r
181 UnalignedPages = EFI_SIZE_TO_PAGES ((UINTN) Memory - AlignedMemory);\r
182 if (UnalignedPages > 0) {\r
183 //\r
184 // Free first unaligned page(s).\r
185 //\r
186 Status = gBS->FreePages (Memory, UnalignedPages);\r
187 ASSERT_EFI_ERROR (Status);\r
188 }\r
189 Memory = (EFI_PHYSICAL_ADDRESS) (AlignedMemory + EFI_PAGES_TO_SIZE (Pages));\r
190 UnalignedPages = RealPages - Pages - UnalignedPages;\r
191 if (UnalignedPages > 0) {\r
192 //\r
193 // Free last unaligned page(s).\r
194 //\r
195 Status = gBS->FreePages (Memory, UnalignedPages);\r
196 ASSERT_EFI_ERROR (Status);\r
197 }\r
198 } else {\r
199 //\r
200 // Do not over-allocate pages in this case.\r
201 //\r
202 Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory);\r
203 if (EFI_ERROR (Status)) {\r
204 return NULL;\r
205 }\r
206 AlignedMemory = (UINTN) Memory;\r
207 }\r
208 return (VOID *) AlignedMemory;\r
209}\r
210\r
211/**\r
212 Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData\r
213 with an alignment specified by Alignment. \r
214\r
215 @param Pages The number of 4 KB pages to allocate.\r
216 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
217 If Alignment is zero, then byte alignment is used.\r
218\r
219 @return The allocated buffer is returned.<BR>\r
220 If Pages is 0, then NULL is returned.<BR>\r
221 If there is not enough memory at the specified alignment remaining to satisfy the request, then NULL is returned.\r
222\r
223**/\r
224VOID *\r
225EFIAPI\r
226AllocateAlignedPages (\r
227 IN UINTN Pages,\r
228 IN UINTN Alignment\r
229 )\r
230{\r
231 return InternalAllocateAlignedPages (EfiBootServicesData, Pages, Alignment);\r
232}\r
233\r
234/**\r
235 Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData\r
236 with an alignment specified by Alignment. \r
237\r
238 @param Pages The number of 4 KB pages to allocate.\r
239 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
240 If Alignment is zero, then byte alignment is used.\r
241\r
242 @return The allocated buffer is returned. If Pages is 0, then NULL is returned.\r
243 If there is not enough memory at the specified alignment remaining to satisfy the request, then NULL is returned.\r
244\r
245**/\r
246VOID *\r
247EFIAPI\r
248AllocateAlignedRuntimePages (\r
249 IN UINTN Pages,\r
250 IN UINTN Alignment\r
251 )\r
252{\r
253 return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment);\r
254}\r
255\r
256/**\r
257 Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment.\r
258\r
259 @param Pages The number of 4 KB pages to allocate.\r
260 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
261 If Alignment is zero, then byte alignment is used.\r
262\r
263 @return The allocated buffer is returned. If Pages is 0, then NULL is returned.\r
264 If there is not enough memory at the specified alignment remaining to satisfy the request, then NULL is returned.\r
265\r
266**/\r
267VOID *\r
268EFIAPI\r
269AllocateAlignedReservedPages (\r
270 IN UINTN Pages,\r
271 IN UINTN Alignment\r
272 )\r
273{\r
274 return InternalAllocateAlignedPages (EfiReservedMemoryType, Pages, Alignment);\r
275}\r
276\r
277/**\r
278 Frees one or more 4KB pages that were previously allocated with \r
279 one of the aligned page allocation functions in the Memory Allocation Library.\r
280\r
281 @param Buffer Pointer to the buffer of pages to free.\r
282 @param Pages The number of 4 KB pages to free.\r
283\r
284**/\r
285VOID\r
286EFIAPI\r
287FreeAlignedPages (\r
288 IN VOID *Buffer,\r
289 IN UINTN Pages\r
290 )\r
291{\r
292 EFI_STATUS Status;\r
293\r
294 ASSERT (Pages != 0);\r
295 Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);\r
296 ASSERT_EFI_ERROR (Status);\r
297}\r
298\r
299/**\r
300 Allocates a buffer of a certain memory type.\r
301\r
302 @param MemoryType The type of memory to allocate.\r
303 @param AllocationSize The number of bytes to allocate.\r
304\r
305 @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned.\r
306 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
307\r
308**/\r
309VOID *\r
310InternalAllocatePool (\r
311 IN EFI_MEMORY_TYPE MemoryType, \r
312 IN UINTN AllocationSize\r
313 )\r
314{\r
315 EFI_STATUS Status;\r
316 VOID *Memory;\r
317\r
318 Status = gBS->AllocatePool (MemoryType, AllocationSize, &Memory);\r
319 if (EFI_ERROR (Status)) {\r
320 Memory = NULL;\r
321 }\r
322 return Memory;\r
323}\r
324\r
325/**\r
326 Allocates a buffer of type EfiBootServicesData.\r
327\r
328 @param AllocationSize The number of bytes to allocate.\r
329\r
330 @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned.\r
331 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
332\r
333**/\r
334VOID *\r
335EFIAPI\r
336AllocatePool (\r
337 IN UINTN AllocationSize\r
338 )\r
339{\r
340 return InternalAllocatePool (EfiBootServicesData, AllocationSize);\r
341}\r
342\r
343/**\r
344 Allocates a buffer of type EfiRuntimeServicesData.\r
345\r
346 @param AllocationSize The number of bytes to allocate.\r
347\r
348 @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned.\r
349 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
350\r
351**/\r
352VOID *\r
353EFIAPI\r
354AllocateRuntimePool (\r
355 IN UINTN AllocationSize\r
356 )\r
357{\r
358 return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize);\r
359}\r
360\r
361/**\r
362 Allocates a buffer of type EfiReservedMemoryType.\r
363\r
364 @param AllocationSize The number of bytes to allocate.\r
365\r
366 @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned.\r
367 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
368\r
369**/\r
370VOID *\r
371EFIAPI\r
372AllocateReservedPool (\r
373 IN UINTN AllocationSize\r
374 )\r
375{\r
376 return InternalAllocatePool (EfiReservedMemoryType, AllocationSize);\r
377}\r
378\r
379/**\r
380 Allocates and zeros a buffer of a certian pool type.\r
381\r
382 @param PoolType The type of memory to allocate.\r
383 @param AllocationSize The number of bytes to allocate and zero.\r
384\r
385 @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned.\r
386 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
387\r
388**/\r
389VOID *\r
390InternalAllocateZeroPool (\r
391 IN EFI_MEMORY_TYPE PoolType, \r
392 IN UINTN AllocationSize\r
393 ) \r
394{\r
395 VOID *Memory;\r
396 Memory = InternalAllocatePool (PoolType, AllocationSize);\r
397 if (Memory != NULL) {\r
398 Memory = ZeroMem (Memory, AllocationSize);\r
399 }\r
400 return Memory;\r
401}\r
402\r
403/**\r
404 Allocates and zeros a buffer of type EfiBootServicesData.\r
405\r
406 @param AllocationSize The number of bytes to allocate and zero.\r
407\r
408 @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned.\r
409 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
410\r
411**/\r
412VOID *\r
413EFIAPI\r
414AllocateZeroPool (\r
415 IN UINTN AllocationSize\r
416 )\r
417{\r
418 return InternalAllocateZeroPool (EfiBootServicesData, AllocationSize);\r
419}\r
420\r
421/**\r
422 Allocates and zeros a buffer of type EfiRuntimeServicesData.\r
423\r
424 @param AllocationSize The number of bytes to allocate and zero.\r
425\r
426 @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned.\r
427 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
428\r
429**/\r
430VOID *\r
431EFIAPI\r
432AllocateRuntimeZeroPool (\r
433 IN UINTN AllocationSize\r
434 )\r
435{\r
436 return InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize);\r
437}\r
438\r
439/**\r
440 Allocates and zeros a buffer of type EfiReservedMemoryType.\r
441\r
442 @param AllocationSize The number of bytes to allocate and zero.\r
443\r
444 @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned.\r
445 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
446\r
447**/\r
448VOID *\r
449EFIAPI\r
450AllocateReservedZeroPool (\r
451 IN UINTN AllocationSize\r
452 )\r
453{\r
454 return InternalAllocateZeroPool (EfiReservedMemoryType, AllocationSize);\r
455}\r
456\r
457/**\r
458 Copies a buffer to an allocated buffer of a certian memory type. \r
459\r
460 @param MemoryType The type of pool to allocate.\r
461 @param AllocationSize The number of bytes to allocate and zero.\r
462 @param Buffer The buffer to copy to the allocated buffer.\r
463\r
464 @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned.\r
465 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
466\r
467**/\r
468VOID *\r
469InternalAllocateCopyPool (\r
470 IN EFI_MEMORY_TYPE PoolType, \r
471 IN UINTN AllocationSize,\r
472 IN CONST VOID *Buffer\r
473 ) \r
474{\r
475 VOID *Memory;\r
476\r
477 Memory = InternalAllocatePool (PoolType, AllocationSize);\r
478 if (Memory != NULL) {\r
479 Memory = CopyMem (Memory, Buffer, AllocationSize);\r
480 }\r
481 return Memory;\r
482} \r
483\r
484/**\r
485 Copies a buffer to an allocated buffer of type EfiBootServicesData. \r
486\r
487 @param AllocationSize The number of bytes to allocate.\r
488 @param Buffer The buffer to copy to the allocated buffer.\r
489\r
490 @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned.\r
491 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
492\r
493**/\r
494VOID *\r
495EFIAPI\r
496AllocateCopyPool (\r
497 IN UINTN AllocationSize,\r
498 IN CONST VOID *Buffer\r
499 )\r
500{\r
501 return InternalAllocateCopyPool (EfiBootServicesData, AllocationSize, Buffer);\r
502}\r
503\r
504/**\r
505 Copies a buffer to an allocated buffer of type EfiRuntimeServicesData. \r
506\r
507 @param AllocationSize The number of bytes to allocate.\r
508 @param Buffer The buffer to copy to the allocated buffer.\r
509\r
510 @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned.\r
511 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
512\r
513**/\r
514VOID *\r
515EFIAPI\r
516AllocateRuntimeCopyPool (\r
517 IN UINTN AllocationSize,\r
518 IN CONST VOID *Buffer\r
519 )\r
520{\r
521 return InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer);\r
522}\r
523\r
524/**\r
525 Copies a buffer to an allocated buffer of type EfiReservedMemoryType. \r
526\r
527 @param AllocationSize The number of bytes to allocate.\r
528 @param Buffer The buffer to copy to the allocated buffer.\r
529\r
530 @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned.\r
531 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
532\r
533**/\r
534VOID *\r
535EFIAPI\r
536AllocateReservedCopyPool (\r
537 IN UINTN AllocationSize,\r
538 IN CONST VOID *Buffer\r
539 )\r
540{\r
541 return InternalAllocateCopyPool (EfiReservedMemoryType, AllocationSize, Buffer);\r
542}\r
543\r
544/**\r
545 Copies a buffer to an allocated buffer of type EfiReservedMemoryType at a specified alignment.\r
546\r
547 @param Buffer Pointer to the buffer to free.\r
548\r
549**/\r
550VOID\r
551EFIAPI\r
552FreePool (\r
553 IN VOID *Buffer\r
554 )\r
555{\r
556 EFI_STATUS Status;\r
557\r
558 Status = gBS->FreePool (Buffer);\r
559 ASSERT_EFI_ERROR (Status);\r
560}\r
561\r
562/**\r
563 Allocates a buffer of a certain pool type at a specified alignment.\r
564\r
565 @param PoolType The type of pool to allocate.\r
566 @param AllocationSize The number of bytes to allocate.\r
567 @param Alignment The requested alignment of the allocation. Must be a power of two. If Alignment is zero, then byte alignment is used.\r
568\r
569 @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned.\r
570 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
571\r
572**/\r
573VOID *\r
574InternalAllocateAlignedPool (\r
575 IN EFI_MEMORY_TYPE PoolType,\r
576 IN UINTN AllocationSize,\r
577 IN UINTN Alignment\r
578 )\r
579{\r
580 VOID *RawAddress;\r
581 UINTN AlignedAddress;\r
582 UINTN AlignmentMask;\r
583 UINTN OverAllocationSize;\r
abea19db 584 UINTN RealAllocationSize;\r
878ddf1f 585 VOID **FreePointer;\r
878ddf1f 586\r
587 //\r
588 // Alignment must be a power of two or zero.\r
589 //\r
590 ASSERT ((Alignment & (Alignment - 1)) == 0);\r
591 \r
592 if (Alignment == 0) {\r
593 AlignmentMask = Alignment;\r
594 } else {\r
595 AlignmentMask = Alignment - 1;\r
596 }\r
597 //\r
598 // Calculate the extra memory size, over-allocate memory pool and get the aligned memory address. \r
599 //\r
600 OverAllocationSize = sizeof (RawAddress) + AlignmentMask;\r
abea19db 601 RealAllocationSize = AllocationSize + OverAllocationSize;\r
a3657e3e 602 //\r
603 // Make sure that AllocationSize plus OverAllocationSize does not overflow. \r
604 //\r
605 ASSERT (RealAllocationSize > AllocationSize); \r
606\r
abea19db 607 RawAddress = InternalAllocatePool (PoolType, RealAllocationSize);\r
608 if (RawAddress == NULL) {\r
878ddf1f 609 return NULL;\r
610 }\r
611 AlignedAddress = ((UINTN) RawAddress + OverAllocationSize) & ~AlignmentMask;\r
612 //\r
613 // Save the original memory address just before the aligned address.\r
614 //\r
615 FreePointer = (VOID **)(AlignedAddress - sizeof (RawAddress));\r
616 *FreePointer = RawAddress;\r
617\r
618 return (VOID *) AlignedAddress;\r
619}\r
620\r
621/**\r
622 Allocates a buffer of type EfiBootServicesData at a specified alignment.\r
623\r
624 @param AllocationSize The number of bytes to allocate.\r
625 @param Alignment The requested alignment of the allocation. Must be a power of two. If Alignment is zero, then byte alignment is used.\r
626\r
627 @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned.\r
628 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
629\r
630**/\r
631VOID *\r
632EFIAPI\r
633AllocateAlignedPool (\r
634 IN UINTN AllocationSize,\r
635 IN UINTN Alignment\r
636 )\r
637{\r
638 return InternalAllocateAlignedPool (EfiBootServicesData, AllocationSize, Alignment);\r
639}\r
640\r
641/**\r
642 Allocates a buffer of type EfiRuntimeServicesData at a specified alignment.\r
643\r
644 @param AllocationSize The number of bytes to allocate.\r
645 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
646 If Alignment is zero, then byte alignment is used.\r
647\r
648 A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned.\r
649 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
650\r
651**/\r
652VOID *\r
653EFIAPI\r
654AllocateAlignedRuntimePool (\r
655 IN UINTN AllocationSize,\r
656 IN UINTN Alignment\r
657 )\r
658{\r
659 return InternalAllocateAlignedPool (EfiRuntimeServicesData, AllocationSize, Alignment);\r
660}\r
661\r
662/**\r
663 Allocates a buffer of type EfiReservedMemoryType at a specified alignment.\r
664\r
665 @param AllocationSize The number of bytes to allocate.\r
666 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
667 If Alignment is zero, then byte alignment is used.\r
668\r
669 @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned.\r
670 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
671\r
672**/\r
673VOID *\r
674EFIAPI\r
675AllocateAlignedReservedPool (\r
676 IN UINTN AllocationSize,\r
677 IN UINTN Alignment\r
678 )\r
679{\r
680 return InternalAllocateAlignedPool (EfiReservedMemoryType, AllocationSize, Alignment);\r
681}\r
682\r
683/**\r
684 Allocates and zeros a buffer of type EfiBootServicesData at a specified alignment.\r
685\r
686 @param PoolType The type of pool to allocate.\r
687 @param AllocationSize The number of bytes to allocate.\r
688 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
689 If Alignment is zero, then byte alignment is used.\r
690\r
691 @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned.\r
692 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
693\r
694**/\r
695VOID *\r
696InternalAllocateAlignedZeroPool (\r
697 IN EFI_MEMORY_TYPE PoolType,\r
698 IN UINTN AllocationSize,\r
699 IN UINTN Alignment\r
700 )\r
701{\r
702 VOID *Memory;\r
703 Memory = InternalAllocateAlignedPool (PoolType, AllocationSize, Alignment);\r
704 if (Memory != NULL) {\r
705 Memory = ZeroMem (Memory, AllocationSize);\r
706 }\r
707 return Memory;\r
708}\r
709\r
710/**\r
711 Allocates and zeros a buffer of type EfiBootServicesData at a specified alignment.\r
712\r
713 @param AllocationSize The number of bytes to allocate.\r
714 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
715 If Alignment is zero, then byte alignment is used.\r
716\r
717 @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned.\r
718 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
719\r
720**/\r
721VOID *\r
722EFIAPI\r
723AllocateAlignedZeroPool (\r
724 IN UINTN AllocationSize,\r
725 IN UINTN Alignment\r
726 )\r
727{\r
728 return InternalAllocateAlignedZeroPool (EfiBootServicesData, AllocationSize, Alignment);\r
729}\r
730\r
731/**\r
732 Allocates and zeros a buffer of type EfiRuntimeServicesData at a specified alignment.\r
733\r
734 @param AllocationSize The number of bytes to allocate.\r
735 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
736 If Alignment is zero, then byte alignment is used.\r
737\r
738 @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned.\r
739 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
740\r
741**/\r
742VOID *\r
743EFIAPI\r
744AllocateAlignedRuntimeZeroPool (\r
745 IN UINTN AllocationSize,\r
746 IN UINTN Alignment\r
747 )\r
748{\r
749 return InternalAllocateAlignedZeroPool (EfiRuntimeServicesData, AllocationSize, Alignment);\r
750}\r
751\r
752/**\r
753 Allocates and zeros a buffer of type EfiReservedMemoryType at a specified alignment.\r
754\r
755 @param AllocationSize The number of bytes to allocate.\r
756 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
757 If Alignment is zero, then byte alignment is used.\r
758\r
759 @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned.\r
760 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
761\r
762**/\r
763VOID *\r
764EFIAPI\r
765AllocateAlignedReservedZeroPool (\r
766 IN UINTN AllocationSize,\r
767 IN UINTN Alignment\r
768 )\r
769{\r
770 return InternalAllocateAlignedZeroPool (EfiReservedMemoryType, AllocationSize, Alignment);\r
771}\r
772\r
773/**\r
774 Copies a buffer to an allocated buffer of type EfiBootServicesData at a specified alignment.\r
775\r
776 @param PoolType The type of pool to allocate.\r
777 @param AllocationSize The number of bytes to allocate.\r
778 @param Buffer The buffer to copy to the allocated buffer.\r
779 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
780 If Alignment is zero, then byte alignment is used.\r
781\r
782 @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned.\r
783 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
784\r
785**/\r
786VOID *\r
787InternalAllocateAlignedCopyPool (\r
788 IN EFI_MEMORY_TYPE PoolType,\r
789 IN UINTN AllocationSize,\r
790 IN CONST VOID *Buffer,\r
791 IN UINTN Alignment\r
792 )\r
793{\r
794 VOID *Memory;\r
795 \r
796 Memory = InternalAllocateAlignedPool (PoolType, AllocationSize, Alignment);\r
797 if (Memory != NULL) {\r
798 Memory = CopyMem (Memory, Buffer, AllocationSize);\r
799 }\r
800 return Memory;\r
801}\r
802\r
803/**\r
804 Copies a buffer to an allocated buffer of type EfiBootServicesData at a specified alignment.\r
805\r
806 @param AllocationSize The number of bytes to allocate.\r
807 @param Buffer The buffer to copy to the allocated buffer.\r
808 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
809 If Alignment is zero, then byte alignment is used.\r
810\r
811 @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned.\r
812 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
813\r
814**/\r
815VOID *\r
816EFIAPI\r
817AllocateAlignedCopyPool (\r
818 IN UINTN AllocationSize,\r
819 IN CONST VOID *Buffer,\r
820 IN UINTN Alignment\r
821 )\r
822{\r
823 return InternalAllocateAlignedCopyPool (EfiBootServicesData, AllocationSize, Buffer, Alignment);\r
824}\r
825\r
826/**\r
827 Copies a buffer to an allocated buffer of type EfiRuntimeServicesData at a specified alignment.\r
828\r
829 @param AllocationSize The number of bytes to allocate.\r
830 @param Buffer The buffer to copy to the allocated buffer.\r
831 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
832 If Alignment is zero, then byte alignment is used.\r
833\r
834 @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned.\r
835 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
836\r
837**/\r
838VOID *\r
839EFIAPI\r
840AllocateAlignedRuntimeCopyPool (\r
841 IN UINTN AllocationSize,\r
842 IN CONST VOID *Buffer,\r
843 IN UINTN Alignment\r
844 )\r
845{\r
846 return InternalAllocateAlignedCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer, Alignment);\r
847}\r
848\r
849/**\r
850 Copies a buffer to an allocated buffer of type EfiReservedMemoryType at a specified alignment.\r
851\r
852 @param AllocationSize The number of bytes to allocate.\r
853 @param Buffer The buffer to copy to the allocated buffer.\r
854 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
855 If Alignment is zero, then byte alignment is used.\r
856\r
857 @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned.\r
858 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
859\r
860**/\r
861VOID *\r
862EFIAPI\r
863AllocateAlignedReservedCopyPool (\r
864 IN UINTN AllocationSize,\r
865 IN CONST VOID *Buffer,\r
866 IN UINTN Alignment\r
867 )\r
868{\r
869 return InternalAllocateAlignedCopyPool (EfiReservedMemoryType, AllocationSize, Buffer, Alignment);\r
870}\r
871\r
872/**\r
873 Frees a buffer that was previously allocated with one of the aligned pool allocation functions \r
874 in the Memory Allocation Library.\r
875\r
876 @param Buffer Pointer to the buffer to free.\r
877\r
878**/\r
879VOID\r
880EFIAPI\r
881FreeAlignedPool (\r
882 IN VOID *Buffer\r
883 )\r
884{\r
885 VOID *RawAddress;\r
886 VOID **FreePointer;\r
887 EFI_STATUS Status;\r
888\r
889 //\r
890 // Get the pre-saved original address in the over-allocate pool.\r
891 //\r
892 FreePointer = (VOID **)((UINTN) Buffer - sizeof (RawAddress));\r
893 RawAddress = *FreePointer;\r
894\r
895 Status = gBS->FreePool (RawAddress);\r
896 ASSERT_EFI_ERROR (Status);\r
897}\r