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