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