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
131 Allocation Library. If it is not possible to free allocated pages, then this function will
134 If Buffer was not allocated with a page allocation function in the Memory Allocation Library,
136 If Pages is zero, then ASSERT().
138 @param Buffer Pointer to the buffer of pages to free.
139 @param Pages The number of 4 KB pages to free.
151 // PEI phase does not support to free pages, so leave it as NOP.
156 Allocates one or more 4KB pages of a certain memory type at a specified alignment.
158 Allocates the number of 4KB pages specified by Pages of a certain memory type with an alignment
159 specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is returned.
160 If there is not enough memory at the specified alignment remaining to satisfy the request, then
162 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
164 @param MemoryType The type of memory to allocate.
165 @param Pages The number of 4 KB pages to allocate.
166 @param Alignment The requested alignment of the allocation. Must be a power of two.
167 If Alignment is zero, then byte alignment is used.
169 @return A pointer to the allocated buffer or NULL if allocation fails.
173 InternalAllocateAlignedPages (
174 IN EFI_MEMORY_TYPE MemoryType
,
183 // Alignment must be a power of two or zero.
185 ASSERT ((Alignment
& (Alignment
- 1)) == 0);
191 // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
193 ASSERT (Pages
<= (MAX_ADDRESS
- EFI_SIZE_TO_PAGES (Alignment
)));
195 // We would rather waste some memory to save PEI code size.
197 Memory
= InternalAllocatePages (MemoryType
, Pages
+ EFI_SIZE_TO_PAGES (Alignment
));
198 if (Alignment
== 0) {
199 AlignmentMask
= Alignment
;
201 AlignmentMask
= Alignment
- 1;
203 return (VOID
*) (UINTN
) (((UINTN
) Memory
+ AlignmentMask
) & ~AlignmentMask
);
207 Allocates one or more 4KB pages of type EfiBootServicesData at a specified alignment.
209 Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData with an
210 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is
211 returned. If there is not enough memory at the specified alignment remaining to satisfy the
212 request, then NULL is returned.
214 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
216 @param Pages The number of 4 KB pages to allocate.
217 @param Alignment The requested alignment of the allocation. Must be a power of two.
218 If Alignment is zero, then byte alignment is used.
220 @return A pointer to the allocated buffer or NULL if allocation fails.
225 AllocateAlignedPages (
230 return InternalAllocateAlignedPages (EfiBootServicesData
, Pages
, Alignment
);
234 Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment.
236 Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData with an
237 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is
238 returned. If there is not enough memory at the specified alignment remaining to satisfy the
239 request, then NULL is returned.
241 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
243 @param Pages The number of 4 KB pages to allocate.
244 @param Alignment The requested alignment of the allocation. Must be a power of two.
245 If Alignment is zero, then byte alignment is used.
247 @return A pointer to the allocated buffer or NULL if allocation fails.
252 AllocateAlignedRuntimePages (
257 return InternalAllocateAlignedPages (EfiRuntimeServicesData
, Pages
, Alignment
);
261 Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment.
263 Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType with an
264 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is
265 returned. If there is not enough memory at the specified alignment remaining to satisfy the
266 request, then NULL is returned.
268 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
270 @param Pages The number of 4 KB pages to allocate.
271 @param Alignment The requested alignment of the allocation. Must be a power of two.
272 If Alignment is zero, then byte alignment is used.
274 @return A pointer to the allocated buffer or NULL if allocation fails.
279 AllocateAlignedReservedPages (
284 return InternalAllocateAlignedPages (EfiReservedMemoryType
, Pages
, Alignment
);
288 Frees one or more 4KB pages that were previously allocated with one of the aligned page
289 allocation functions in the Memory Allocation Library.
291 Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer
292 must have been allocated on a previous call to the aligned page allocation services of the Memory
293 Allocation Library. If it is not possible to free allocated pages, then this function will
296 If Buffer was not allocated with an aligned page allocation function in the Memory Allocation
297 Library, then ASSERT().
298 If Pages is zero, then ASSERT().
300 @param Buffer Pointer to the buffer of pages to free.
301 @param Pages The number of 4 KB pages to free.
313 // PEI phase does not support to free pages, so leave it as NOP.
318 Allocates a buffer of a certain pool type.
320 Allocates the number bytes specified by AllocationSize of a certain pool type and returns a
321 pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
322 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
324 @param MemoryType The type of memory to allocate.
325 @param AllocationSize The number of bytes to allocate.
327 @return A pointer to the allocated buffer or NULL if allocation fails.
331 InternalAllocatePool (
332 IN EFI_MEMORY_TYPE MemoryType
,
333 IN UINTN AllocationSize
337 // If we need lots of small runtime/reserved memory type from PEI in the future,
338 // we can consider providing a more complex algorithm that allocates runtime pages and
339 // provide pool allocations from those pages.
341 return InternalAllocatePages (MemoryType
, EFI_SIZE_TO_PAGES (AllocationSize
));
345 Allocates a buffer of type EfiBootServicesData.
347 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a
348 pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
349 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
351 @param AllocationSize The number of bytes to allocate.
353 @return A pointer to the allocated buffer or NULL if allocation fails.
359 IN UINTN AllocationSize
365 Status
= PeiServicesAllocatePool (AllocationSize
, &Buffer
);
366 if (EFI_ERROR (Status
)) {
373 Allocates a buffer of type EfiRuntimeServicesData.
375 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData and returns
376 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
377 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
379 @param AllocationSize The number of bytes to allocate.
381 @return A pointer to the allocated buffer or NULL if allocation fails.
386 AllocateRuntimePool (
387 IN UINTN AllocationSize
390 return InternalAllocatePool (EfiRuntimeServicesData
, AllocationSize
);
394 Allocates a buffer of type EfiReservedMemoryType.
396 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType and returns
397 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
398 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
400 @param AllocationSize The number of bytes to allocate.
402 @return A pointer to the allocated buffer or NULL if allocation fails.
407 AllocateReservedPool (
408 IN UINTN AllocationSize
411 return InternalAllocatePool (EfiReservedMemoryType
, AllocationSize
);
415 Allocates and zeros a buffer of a certain pool type.
417 Allocates the number bytes specified by AllocationSize of a certain pool type, clears the buffer
418 with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a valid
419 buffer of 0 size is returned. If there is not enough memory remaining to satisfy the request,
420 then NULL is returned.
422 @param PoolType The type of memory to allocate.
423 @param AllocationSize The number of bytes to allocate and zero.
425 @return A pointer to the allocated buffer or NULL if allocation fails.
429 InternalAllocateZeroPool (
430 IN EFI_MEMORY_TYPE PoolType
,
431 IN UINTN AllocationSize
436 Memory
= InternalAllocatePool (PoolType
, AllocationSize
);
437 if (Memory
!= NULL
) {
438 Memory
= ZeroMem (Memory
, AllocationSize
);
444 Allocates and zeros a buffer of type EfiBootServicesData.
446 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the
447 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a
448 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the
449 request, then NULL is returned.
451 @param AllocationSize The number of bytes to allocate and zero.
453 @return A pointer to the allocated buffer or NULL if allocation fails.
459 IN UINTN AllocationSize
464 Memory
= AllocatePool (AllocationSize
);
465 if (Memory
!= NULL
) {
466 Memory
= ZeroMem (Memory
, AllocationSize
);
472 Allocates and zeros a buffer of type EfiRuntimeServicesData.
474 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, clears the
475 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a
476 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the
477 request, then NULL is returned.
479 @param AllocationSize The number of bytes to allocate and zero.
481 @return A pointer to the allocated buffer or NULL if allocation fails.
486 AllocateRuntimeZeroPool (
487 IN UINTN AllocationSize
490 return InternalAllocateZeroPool (EfiRuntimeServicesData
, AllocationSize
);
494 Allocates and zeros a buffer of type EfiReservedMemoryType.
496 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, clears the
497 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a
498 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the
499 request, then NULL is returned.
501 @param AllocationSize The number of bytes to allocate and zero.
503 @return A pointer to the allocated buffer or NULL if allocation fails.
508 AllocateReservedZeroPool (
509 IN UINTN AllocationSize
512 return InternalAllocateZeroPool (EfiReservedMemoryType
, AllocationSize
);
516 Copies a buffer to an allocated buffer of a certain pool type.
518 Allocates the number bytes specified by AllocationSize of a certain pool type, copies
519 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
520 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there
521 is not enough memory remaining to satisfy the request, then NULL is returned.
522 If Buffer is NULL, then ASSERT().
523 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
525 @param PoolType The type of pool to allocate.
526 @param AllocationSize The number of bytes to allocate and zero.
527 @param Buffer The buffer to copy to the allocated buffer.
529 @return A pointer to the allocated buffer or NULL if allocation fails.
533 InternalAllocateCopyPool (
534 IN EFI_MEMORY_TYPE PoolType
,
535 IN UINTN AllocationSize
,
536 IN CONST VOID
*Buffer
541 ASSERT (Buffer
!= NULL
);
542 ASSERT (AllocationSize
<= (MAX_ADDRESS
- (UINTN
) Buffer
+ 1));
544 Memory
= InternalAllocatePool (PoolType
, AllocationSize
);
545 if (Memory
!= NULL
) {
546 Memory
= CopyMem (Memory
, Buffer
, AllocationSize
);
552 Copies a buffer to an allocated buffer of type EfiBootServicesData.
554 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, copies
555 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
556 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there
557 is not enough memory remaining to satisfy the request, then NULL is returned.
559 If Buffer is NULL, then ASSERT().
560 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
562 @param AllocationSize The number of bytes to allocate and zero.
563 @param Buffer The buffer to copy to the allocated buffer.
565 @return A pointer to the allocated buffer or NULL if allocation fails.
571 IN UINTN AllocationSize
,
572 IN CONST VOID
*Buffer
577 ASSERT (Buffer
!= NULL
);
578 ASSERT (AllocationSize
<= (MAX_ADDRESS
- (UINTN
) Buffer
+ 1));
580 Memory
= AllocatePool (AllocationSize
);
581 if (Memory
!= NULL
) {
582 Memory
= CopyMem (Memory
, Buffer
, AllocationSize
);
588 Copies a buffer to an allocated buffer of type EfiRuntimeServicesData.
590 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, copies
591 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
592 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there
593 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().
598 @param AllocationSize The number of bytes to allocate and zero.
599 @param Buffer The buffer to copy to the allocated buffer.
601 @return A pointer to the allocated buffer or NULL if allocation fails.
606 AllocateRuntimeCopyPool (
607 IN UINTN AllocationSize
,
608 IN CONST VOID
*Buffer
611 return InternalAllocateCopyPool (EfiRuntimeServicesData
, AllocationSize
, Buffer
);
615 Copies a buffer to an allocated buffer of type EfiReservedMemoryType.
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.
622 If Buffer is NULL, then ASSERT().
623 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
625 @param AllocationSize The number of bytes to allocate and zero.
626 @param Buffer The buffer to copy to the allocated buffer.
628 @return A pointer to the allocated buffer or NULL if allocation fails.
633 AllocateReservedCopyPool (
634 IN UINTN AllocationSize
,
635 IN CONST VOID
*Buffer
638 return InternalAllocateCopyPool (EfiReservedMemoryType
, AllocationSize
, Buffer
);
642 Reallocates a buffer of a specified memory type.
644 Allocates and zeros the number bytes specified by NewSize from memory of the type
645 specified by PoolType. If OldBuffer is not NULL, then the smaller of OldSize and
646 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
647 OldBuffer is freed. A pointer to the newly allocated buffer is returned.
648 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not
649 enough memory remaining to satisfy the request, then NULL is returned.
651 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
652 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
654 @param PoolType The type of pool to allocate.
655 @param OldSize The size, in bytes, of OldBuffer.
656 @param NewSize The size, in bytes, of the buffer to reallocate.
657 @param OldBuffer The buffer to copy to the allocated buffer. This is an optional
658 parameter that may be NULL.
660 @return A pointer to the allocated buffer or NULL if allocation fails.
664 InternalReallocatePool (
665 IN EFI_MEMORY_TYPE PoolType
,
668 IN VOID
*OldBuffer OPTIONAL
673 NewBuffer
= InternalAllocateZeroPool (PoolType
, NewSize
);
674 if (NewBuffer
!= NULL
&& OldBuffer
!= NULL
) {
675 CopyMem (NewBuffer
, OldBuffer
, MIN (OldSize
, NewSize
));
676 FreePool (OldBuffer
);
682 Reallocates a buffer of type EfiBootServicesData.
684 Allocates and zeros the number bytes specified by NewSize from memory of type
685 EfiBootServicesData. If OldBuffer is not NULL, then the smaller of OldSize and
686 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
687 OldBuffer is freed. A pointer to the newly allocated buffer is returned.
688 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not
689 enough memory remaining to satisfy the request, then NULL is returned.
691 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
692 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
694 @param OldSize The size, in bytes, of OldBuffer.
695 @param NewSize The size, in bytes, of the buffer to reallocate.
696 @param OldBuffer The buffer to copy to the allocated buffer. This is an optional
697 parameter that may be NULL.
699 @return A pointer to the allocated buffer or NULL if allocation fails.
707 IN VOID
*OldBuffer OPTIONAL
710 return InternalReallocatePool (EfiBootServicesData
, OldSize
, NewSize
, OldBuffer
);
714 Reallocates a buffer of type EfiRuntimeServicesData.
716 Allocates and zeros the number bytes specified by NewSize from memory of type
717 EfiRuntimeServicesData. If OldBuffer is not NULL, then the smaller of OldSize and
718 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
719 OldBuffer is freed. A pointer to the newly allocated buffer is returned.
720 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not
721 enough memory remaining to satisfy the request, then NULL is returned.
723 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
724 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
726 @param OldSize The size, in bytes, of OldBuffer.
727 @param NewSize The size, in bytes, of the buffer to reallocate.
728 @param OldBuffer The buffer to copy to the allocated buffer. This is an optional
729 parameter that may be NULL.
731 @return A pointer to the allocated buffer or NULL if allocation fails.
736 ReallocateRuntimePool (
739 IN VOID
*OldBuffer OPTIONAL
742 return InternalReallocatePool (EfiRuntimeServicesData
, OldSize
, NewSize
, OldBuffer
);
746 Reallocates a buffer of type EfiReservedMemoryType.
748 Allocates and zeros the number bytes specified by NewSize from memory of type
749 EfiReservedMemoryType. If OldBuffer is not NULL, then the smaller of OldSize and
750 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
751 OldBuffer is freed. A pointer to the newly allocated buffer is returned.
752 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not
753 enough memory remaining to satisfy the request, then NULL is returned.
755 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
756 is greater than (MAX_ADDRESS - OldBuffer + 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. If it is not possible to free pool
783 resources, then this function will perform no actions.
785 If Buffer was not allocated with a pool allocation function in the Memory Allocation Library,
788 @param Buffer Pointer to the buffer to free.
798 // PEI phase does not support to free pool, so leave it as NOP.