2 Support routines for memory allocation routines
3 based on PeiService for PEI phase drivers.
5 Copyright (c) 2006 - 2008, Intel Corporation<BR>
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 #include <Library/MemoryAllocationLib.h>
21 #include <Library/PeiServicesLib.h>
22 #include <Library/BaseMemoryLib.h>
23 #include <Library/DebugLib.h>
27 Allocates one or more 4KB pages of a certain memory type.
29 Allocates the number of 4KB pages of a certain memory type and returns a pointer to the allocated
30 buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL is returned.
31 If there is not enough memory remaining to satisfy the request, then NULL is returned.
33 @param MemoryType The type of memory to allocate.
34 @param Pages The number of 4 KB pages to allocate.
36 @return A pointer to the allocated buffer or NULL if allocation fails.
40 InternalAllocatePages (
41 IN EFI_MEMORY_TYPE MemoryType
,
46 EFI_PHYSICAL_ADDRESS Memory
;
52 Status
= PeiServicesAllocatePages (MemoryType
, Pages
, &Memory
);
53 if (EFI_ERROR (Status
)) {
56 return (VOID
*) (UINTN
) Memory
;
60 Allocates one or more 4KB pages of type EfiBootServicesData.
62 Allocates the number of 4KB pages of type EfiBootServicesData and returns a pointer to the
63 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL
64 is returned. If there is not enough memory remaining to satisfy the request, then NULL is
67 @param Pages The number of 4 KB pages to allocate.
69 @return A pointer to the allocated buffer or NULL if allocation fails.
78 return InternalAllocatePages (EfiBootServicesData
, Pages
);
82 Allocates one or more 4KB pages of type EfiRuntimeServicesData.
84 Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the
85 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL
86 is returned. If there is not enough memory remaining to satisfy the request, then NULL is
89 @param Pages The number of 4 KB pages to allocate.
91 @return A pointer to the allocated buffer or NULL if allocation fails.
96 AllocateRuntimePages (
100 return InternalAllocatePages (EfiRuntimeServicesData
, Pages
);
104 Allocates one or more 4KB pages of type EfiReservedMemoryType.
106 Allocates the number of 4KB pages of type EfiReservedMemoryType and returns a pointer to the
107 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL
108 is returned. If there is not enough memory remaining to satisfy the request, then NULL is
111 @param Pages The number of 4 KB pages to allocate.
113 @return A pointer to the allocated buffer or NULL if allocation fails.
118 AllocateReservedPages (
122 return InternalAllocatePages (EfiReservedMemoryType
, Pages
);
126 Frees one or more 4KB pages that were previously allocated with one of the page allocation
127 functions in the Memory Allocation Library.
129 Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer
130 must have been allocated on a previous call to the page allocation services of the Memory
133 If Buffer was not allocated with a page allocation function in the Memory Allocation Library,
135 If Pages is zero, then ASSERT().
137 @param Buffer Pointer to the buffer of pages to free.
138 @param Pages The number of 4 KB pages to free.
149 // PEI phase does not support to free pages, so leave it as NOP.
154 Allocates one or more 4KB pages of a certain memory type at a specified alignment.
156 Allocates the number of 4KB pages specified by Pages of a certain memory type with an alignment
157 specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is returned.
158 If there is not enough memory at the specified alignment remaining to satisfy the request, then
160 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
162 @param MemoryType The type of memory to allocate.
163 @param Pages The number of 4 KB pages to allocate.
164 @param Alignment The requested alignment of the allocation. Must be a power of two.
165 If Alignment is zero, then byte alignment is used.
167 @return A pointer to the allocated buffer or NULL if allocation fails.
171 InternalAllocateAlignedPages (
172 IN EFI_MEMORY_TYPE MemoryType
,
181 // Alignment must be a power of two or zero.
183 ASSERT ((Alignment
& (Alignment
- 1)) == 0);
189 // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
191 ASSERT (Pages
<= (MAX_ADDRESS
- EFI_SIZE_TO_PAGES (Alignment
)));
193 // We would rather waste some memory to save PEI code size.
195 Memory
= InternalAllocatePages (MemoryType
, Pages
+ EFI_SIZE_TO_PAGES (Alignment
));
196 if (Alignment
== 0) {
197 AlignmentMask
= Alignment
;
199 AlignmentMask
= Alignment
- 1;
201 return (VOID
*) (UINTN
) (((UINTN
) Memory
+ AlignmentMask
) & ~AlignmentMask
);
205 Allocates one or more 4KB pages of type EfiBootServicesData at a specified alignment.
207 Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData with an
208 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is
209 returned. If there is not enough memory at the specified alignment remaining to satisfy the
210 request, then NULL is returned.
212 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
214 @param Pages The number of 4 KB pages to allocate.
215 @param Alignment The requested alignment of the allocation. Must be a power of two.
216 If Alignment is zero, then byte alignment is used.
218 @return A pointer to the allocated buffer or NULL if allocation fails.
223 AllocateAlignedPages (
228 return InternalAllocateAlignedPages (EfiBootServicesData
, Pages
, Alignment
);
232 Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment.
234 Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData with an
235 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is
236 returned. If there is not enough memory at the specified alignment remaining to satisfy the
237 request, then NULL is returned.
239 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
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.
245 @return A pointer to the allocated buffer or NULL if allocation fails.
250 AllocateAlignedRuntimePages (
255 return InternalAllocateAlignedPages (EfiRuntimeServicesData
, Pages
, Alignment
);
259 Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment.
261 Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType 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.
266 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
268 @param Pages The number of 4 KB pages to allocate.
269 @param Alignment The requested alignment of the allocation. Must be a power of two.
270 If Alignment is zero, then byte alignment is used.
272 @return A pointer to the allocated buffer or NULL if allocation fails.
277 AllocateAlignedReservedPages (
282 return InternalAllocateAlignedPages (EfiReservedMemoryType
, Pages
, Alignment
);
286 Frees one or more 4KB pages that were previously allocated with one of the aligned page
287 allocation functions in the Memory Allocation Library.
289 Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer
290 must have been allocated on a previous call to the aligned page allocation services of the Memory
293 If Buffer was not allocated with an aligned page allocation function in the Memory Allocation
294 Library, then ASSERT().
295 If Pages is zero, then ASSERT().
297 @param Buffer Pointer to the buffer of pages to free.
298 @param Pages The number of 4 KB pages to free.
309 // PEI phase does not support to free pages, so leave it as NOP.
314 Allocates a buffer of a certain pool type.
316 Allocates the number bytes specified by AllocationSize of a certain pool type and returns a
317 pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
318 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
320 @param MemoryType The type of memory to allocate.
321 @param AllocationSize The number of bytes to allocate.
323 @return A pointer to the allocated buffer or NULL if allocation fails.
327 InternalAllocatePool (
328 IN EFI_MEMORY_TYPE MemoryType
,
329 IN UINTN AllocationSize
333 // If we need lots of small runtime/reserved memory type from PEI in the future,
334 // we can consider providing a more complex algorithm that allocates runtime pages and
335 // provide pool allocations from those pages.
337 return InternalAllocatePages (MemoryType
, EFI_SIZE_TO_PAGES (AllocationSize
));
341 Allocates a buffer of type EfiBootServicesData.
343 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a
344 pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
345 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
347 @param AllocationSize The number of bytes to allocate.
349 @return A pointer to the allocated buffer or NULL if allocation fails.
355 IN UINTN AllocationSize
361 Status
= PeiServicesAllocatePool (AllocationSize
, &Buffer
);
362 if (EFI_ERROR (Status
)) {
369 Allocates a buffer of type EfiRuntimeServicesData.
371 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData and returns
372 a 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.
375 @param AllocationSize The number of bytes to allocate.
377 @return A pointer to the allocated buffer or NULL if allocation fails.
382 AllocateRuntimePool (
383 IN UINTN AllocationSize
386 return InternalAllocatePool (EfiRuntimeServicesData
, AllocationSize
);
390 Allocates a buffer of type EfiReservedMemoryType.
392 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType 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.
396 @param AllocationSize The number of bytes to allocate.
398 @return A pointer to the allocated buffer or NULL if allocation fails.
403 AllocateReservedPool (
404 IN UINTN AllocationSize
407 return InternalAllocatePool (EfiReservedMemoryType
, AllocationSize
);
411 Allocates and zeros a buffer of a certian pool type.
413 Allocates the number bytes specified by AllocationSize of a certian pool type, clears the buffer
414 with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a valid
415 buffer of 0 size is returned. If there is not enough memory remaining to satisfy the request,
416 then NULL is returned.
418 @param PoolType The type of memory to allocate.
419 @param AllocationSize The number of bytes to allocate and zero.
421 @return A pointer to the allocated buffer or NULL if allocation fails.
425 InternalAllocateZeroPool (
426 IN EFI_MEMORY_TYPE PoolType
,
427 IN UINTN AllocationSize
432 Memory
= InternalAllocatePool (PoolType
, AllocationSize
);
433 if (Memory
!= NULL
) {
434 Memory
= ZeroMem (Memory
, AllocationSize
);
440 Allocates and zeros a buffer of type EfiBootServicesData.
442 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the
443 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a
444 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the
445 request, then NULL is returned.
447 @param AllocationSize The number of bytes to allocate and zero.
449 @return A pointer to the allocated buffer or NULL if allocation fails.
455 IN UINTN AllocationSize
460 Memory
= AllocatePool (AllocationSize
);
461 if (Memory
!= NULL
) {
462 Memory
= ZeroMem (Memory
, AllocationSize
);
468 Allocates and zeros a buffer of type EfiRuntimeServicesData.
470 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, clears the
471 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a
472 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the
473 request, then NULL is returned.
475 @param AllocationSize The number of bytes to allocate and zero.
477 @return A pointer to the allocated buffer or NULL if allocation fails.
482 AllocateRuntimeZeroPool (
483 IN UINTN AllocationSize
486 return InternalAllocateZeroPool (EfiRuntimeServicesData
, AllocationSize
);
490 Allocates and zeros a buffer of type EfiReservedMemoryType.
492 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, clears the
493 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a
494 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the
495 request, then NULL is returned.
497 @param AllocationSize The number of bytes to allocate and zero.
499 @return A pointer to the allocated buffer or NULL if allocation fails.
504 AllocateReservedZeroPool (
505 IN UINTN AllocationSize
508 return InternalAllocateZeroPool (EfiReservedMemoryType
, AllocationSize
);
512 Copies a buffer to an allocated buffer of a certian pool type.
514 Allocates the number bytes specified by AllocationSize of a certian pool type, copies
515 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
516 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there
517 is not enough memory remaining to satisfy the request, then NULL is returned.
518 If Buffer is NULL, then ASSERT().
519 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
521 @param PoolType The type of pool to allocate.
522 @param AllocationSize The number of bytes to allocate and zero.
523 @param Buffer The buffer to copy to the allocated buffer.
525 @return A pointer to the allocated buffer or NULL if allocation fails.
529 InternalAllocateCopyPool (
530 IN EFI_MEMORY_TYPE PoolType
,
531 IN UINTN AllocationSize
,
532 IN CONST VOID
*Buffer
537 ASSERT (Buffer
!= NULL
);
538 ASSERT (AllocationSize
<= (MAX_ADDRESS
- (UINTN
) Buffer
+ 1));
540 Memory
= InternalAllocatePool (PoolType
, AllocationSize
);
541 if (Memory
!= NULL
) {
542 Memory
= CopyMem (Memory
, Buffer
, AllocationSize
);
548 Copies a buffer to an allocated buffer of type EfiBootServicesData.
550 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, copies
551 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
552 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there
553 is not enough memory remaining to satisfy the request, then NULL is returned.
555 If Buffer is NULL, then ASSERT().
556 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
558 @param AllocationSize The number of bytes to allocate and zero.
559 @param Buffer The buffer to copy to the allocated buffer.
561 @return A pointer to the allocated buffer or NULL if allocation fails.
567 IN UINTN AllocationSize
,
568 IN CONST VOID
*Buffer
573 ASSERT (Buffer
!= NULL
);
574 ASSERT (AllocationSize
<= (MAX_ADDRESS
- (UINTN
) Buffer
+ 1));
576 Memory
= AllocatePool (AllocationSize
);
577 if (Memory
!= NULL
) {
578 Memory
= CopyMem (Memory
, Buffer
, AllocationSize
);
584 Copies a buffer to an allocated buffer of type EfiRuntimeServicesData.
586 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, copies
587 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
588 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there
589 is not enough memory remaining to satisfy the request, then NULL is returned.
591 If Buffer is NULL, then ASSERT().
592 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
594 @param AllocationSize The number of bytes to allocate and zero.
595 @param Buffer The buffer to copy to the allocated buffer.
597 @return A pointer to the allocated buffer or NULL if allocation fails.
602 AllocateRuntimeCopyPool (
603 IN UINTN AllocationSize
,
604 IN CONST VOID
*Buffer
607 return InternalAllocateCopyPool (EfiRuntimeServicesData
, AllocationSize
, Buffer
);
611 Copies a buffer to an allocated buffer of type EfiReservedMemoryType.
613 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, copies
614 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
615 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there
616 is not enough memory remaining to satisfy the request, then NULL is returned.
618 If Buffer is NULL, then ASSERT().
619 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
621 @param AllocationSize The number of bytes to allocate and zero.
622 @param Buffer The buffer to copy to the allocated buffer.
624 @return A pointer to the allocated buffer or NULL if allocation fails.
629 AllocateReservedCopyPool (
630 IN UINTN AllocationSize
,
631 IN CONST VOID
*Buffer
634 return InternalAllocateCopyPool (EfiReservedMemoryType
, AllocationSize
, Buffer
);
638 Reallocates a buffer of a specified memory type.
640 Allocates and zeros the number bytes specified by NewSize from memory of the type
641 specified by PoolType. If OldBuffer is not NULL, then the smaller of OldSize and
642 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
643 OldBuffer is freed. A pointer to the newly allocated buffer is returned.
644 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not
645 enough memory remaining to satisfy the request, then NULL is returned.
647 If OldBuffer is NULL, then ASSERT().
648 If NewSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
649 If OldSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
651 @param PoolType The type of pool to allocate.
652 @param OldSize The size, in bytes, of OldBuffer.
653 @param NewSize The size, in bytes, of the buffer to reallocate.
654 @param OldBuffer The buffer to copy to the allocated buffer. This is an optional
655 parameter that may be NULL.
657 @return A pointer to the allocated buffer or NULL if allocation fails.
661 InternalReallocatePool (
662 IN EFI_MEMORY_TYPE PoolType
,
665 IN VOID
*OldBuffer OPTIONAL
670 NewBuffer
= AllocateZeroPool (NewSize
);
671 if (NewBuffer
!= NULL
&& OldBuffer
!= NULL
) {
672 CopyMem (NewBuffer
, OldBuffer
, MIN (OldSize
, NewSize
));
673 FreePool (OldBuffer
);
679 Reallocates a buffer of type EfiBootServicesData.
681 Allocates and zeros the number bytes specified by NewSize from memory of type
682 EfiBootServicesData. If OldBuffer is not NULL, then the smaller of OldSize and
683 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
684 OldBuffer is freed. A pointer to the newly allocated buffer is returned.
685 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not
686 enough memory remaining to satisfy the request, then NULL is returned.
688 If OldBuffer is NULL, then ASSERT().
689 If NewSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
690 If OldSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
692 @param OldSize The size, in bytes, of OldBuffer.
693 @param NewSize The size, in bytes, of the buffer to reallocate.
694 @param OldBuffer The buffer to copy to the allocated buffer. This is an optional
695 parameter that may be NULL.
697 @return A pointer to the allocated buffer or NULL if allocation fails.
705 IN VOID
*OldBuffer OPTIONAL
708 return InternalReallocatePool (EfiBootServicesData
, OldSize
, NewSize
, OldBuffer
);
712 Reallocates a buffer of type EfiRuntimeServicesData.
714 Allocates and zeros the number bytes specified by NewSize from memory of type
715 EfiRuntimeServicesData. If OldBuffer is not NULL, then the smaller of OldSize and
716 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
717 OldBuffer is freed. A pointer to the newly allocated buffer is returned.
718 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not
719 enough memory remaining to satisfy the request, then NULL is returned.
721 If OldBuffer is NULL, then ASSERT().
722 If NewSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
723 If OldSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
725 @param OldSize The size, in bytes, of OldBuffer.
726 @param NewSize The size, in bytes, of the buffer to reallocate.
727 @param OldBuffer The buffer to copy to the allocated buffer. This is an optional
728 parameter that may be NULL.
730 @return A pointer to the allocated buffer or NULL if allocation fails.
735 ReallocateRuntimePool (
738 IN VOID
*OldBuffer OPTIONAL
741 return InternalReallocatePool (EfiRuntimeServicesData
, OldSize
, NewSize
, OldBuffer
);
745 Reallocates a buffer of type EfiReservedMemoryType.
747 Allocates and zeros the number bytes specified by NewSize from memory of type
748 EfiReservedMemoryType. If OldBuffer is not NULL, then the smaller of OldSize and
749 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
750 OldBuffer is freed. A pointer to the newly allocated buffer is returned.
751 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not
752 enough memory remaining to satisfy the request, then NULL is returned.
754 If OldBuffer is NULL, then ASSERT().
755 If NewSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
756 If OldSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
758 @param OldSize The size, in bytes, of OldBuffer.
759 @param NewSize The size, in bytes, of the buffer to reallocate.
760 @param OldBuffer The buffer to copy to the allocated buffer. This is an optional
761 parameter that may be NULL.
763 @return A pointer to the allocated buffer or NULL if allocation fails.
768 ReallocateReservedPool (
771 IN VOID
*OldBuffer OPTIONAL
774 return InternalReallocatePool (EfiReservedMemoryType
, OldSize
, NewSize
, OldBuffer
);
778 Frees a buffer that was previously allocated with one of the pool allocation functions in the
779 Memory Allocation Library.
781 Frees the buffer specified by Buffer. Buffer must have been allocated on a previous call to the
782 pool allocation services of the Memory Allocation Library.
784 If Buffer was not allocated with a pool allocation function in the Memory Allocation Library,
787 @param Buffer Pointer to the buffer to free.
797 // PEI phase does not support to free pool, so leave it as NOP.