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