2 Support routines for memory allocation routines
3 based on PeiService for PEI phase drivers.
5 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
6 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 The 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.
167 Must be a power of two.
168 If Alignment is zero, then byte alignment is used.
170 @return A pointer to the allocated buffer or NULL if allocation fails.
174 InternalAllocateAlignedPages (
175 IN EFI_MEMORY_TYPE MemoryType
,
184 // Alignment must be a power of two or zero.
186 ASSERT ((Alignment
& (Alignment
- 1)) == 0);
192 // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
194 ASSERT (Pages
<= (MAX_ADDRESS
- EFI_SIZE_TO_PAGES (Alignment
)));
196 // We would rather waste some memory to save PEI code size.
198 Memory
= InternalAllocatePages (MemoryType
, Pages
+ EFI_SIZE_TO_PAGES (Alignment
));
199 if (Alignment
== 0) {
200 AlignmentMask
= Alignment
;
202 AlignmentMask
= Alignment
- 1;
204 return (VOID
*) (UINTN
) (((UINTN
) Memory
+ AlignmentMask
) & ~AlignmentMask
);
208 Allocates one or more 4KB pages of type EfiBootServicesData at a specified alignment.
210 Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData with an
211 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is
212 returned. If there is not enough memory at the specified alignment remaining to satisfy the
213 request, then NULL is returned.
215 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
217 @param Pages The number of 4 KB pages to allocate.
218 @param Alignment The requested alignment of the allocation.
219 Must be a power of two.
220 If Alignment is zero, then byte alignment is used.
222 @return A pointer to the allocated buffer or NULL if allocation fails.
227 AllocateAlignedPages (
232 return InternalAllocateAlignedPages (EfiBootServicesData
, Pages
, Alignment
);
236 Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment.
238 Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData with an
239 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is
240 returned. If there is not enough memory at the specified alignment remaining to satisfy the
241 request, then NULL is returned.
243 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
245 @param Pages The number of 4 KB pages to allocate.
246 @param Alignment The requested alignment of the allocation.
247 Must be a power of two.
248 If Alignment is zero, then byte alignment is used.
250 @return A pointer to the allocated buffer or NULL if allocation fails.
255 AllocateAlignedRuntimePages (
260 return InternalAllocateAlignedPages (EfiRuntimeServicesData
, Pages
, Alignment
);
264 Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment.
266 Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType with an
267 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is
268 returned. If there is not enough memory at the specified alignment remaining to satisfy the
269 request, then NULL is returned.
271 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
273 @param Pages The number of 4 KB pages to allocate.
274 @param Alignment The requested alignment of the allocation.
275 Must be a power of two.
276 If Alignment is zero, then byte alignment is used.
278 @return A pointer to the allocated buffer or NULL if allocation fails.
283 AllocateAlignedReservedPages (
288 return InternalAllocateAlignedPages (EfiReservedMemoryType
, Pages
, Alignment
);
292 Frees one or more 4KB pages that were previously allocated with one of the aligned page
293 allocation functions in the Memory Allocation Library.
295 Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer
296 must have been allocated on a previous call to the aligned page allocation services of the Memory
297 Allocation Library. If it is not possible to free allocated pages, then this function will
300 If Buffer was not allocated with an aligned page allocation function in the Memory Allocation
301 Library, then ASSERT().
302 If Pages is zero, then ASSERT().
304 @param Buffer The pointer to the buffer of pages to free.
305 @param Pages The number of 4 KB pages to free.
317 // PEI phase does not support to free pages, so leave it as NOP.
322 Allocates a buffer of a certain pool type.
324 Allocates the number bytes specified by AllocationSize of a certain pool type and returns a
325 pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
326 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
328 @param MemoryType The type of memory to allocate.
329 @param AllocationSize The number of bytes to allocate.
331 @return A pointer to the allocated buffer or NULL if allocation fails.
335 InternalAllocatePool (
336 IN EFI_MEMORY_TYPE MemoryType
,
337 IN UINTN AllocationSize
341 // If we need lots of small runtime/reserved memory type from PEI in the future,
342 // we can consider providing a more complex algorithm that allocates runtime pages and
343 // provide pool allocations from those pages.
345 return InternalAllocatePages (MemoryType
, EFI_SIZE_TO_PAGES (AllocationSize
));
349 Allocates a buffer of type EfiBootServicesData.
351 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a
352 pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
353 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
355 @param AllocationSize The number of bytes to allocate.
357 @return A pointer to the allocated buffer or NULL if allocation fails.
363 IN UINTN AllocationSize
369 Status
= PeiServicesAllocatePool (AllocationSize
, &Buffer
);
370 if (EFI_ERROR (Status
)) {
377 Allocates a buffer of type EfiRuntimeServicesData.
379 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData and returns
380 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
381 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
383 @param AllocationSize The number of bytes to allocate.
385 @return A pointer to the allocated buffer or NULL if allocation fails.
390 AllocateRuntimePool (
391 IN UINTN AllocationSize
394 return InternalAllocatePool (EfiRuntimeServicesData
, AllocationSize
);
398 Allocates a buffer of type EfiReservedMemoryType.
400 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType and returns
401 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
402 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
404 @param AllocationSize The number of bytes to allocate.
406 @return A pointer to the allocated buffer or NULL if allocation fails.
411 AllocateReservedPool (
412 IN UINTN AllocationSize
415 return InternalAllocatePool (EfiReservedMemoryType
, AllocationSize
);
419 Allocates and zeros a buffer of a certain pool type.
421 Allocates the number bytes specified by AllocationSize of a certain pool type, clears the buffer
422 with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a valid
423 buffer of 0 size is returned. If there is not enough memory remaining to satisfy the request,
424 then NULL is returned.
426 @param PoolType The type of memory to allocate.
427 @param AllocationSize The number of bytes to allocate and zero.
429 @return A pointer to the allocated buffer or NULL if allocation fails.
433 InternalAllocateZeroPool (
434 IN EFI_MEMORY_TYPE PoolType
,
435 IN UINTN AllocationSize
440 Memory
= InternalAllocatePool (PoolType
, AllocationSize
);
441 if (Memory
!= NULL
) {
442 Memory
= ZeroMem (Memory
, AllocationSize
);
448 Allocates and zeros a buffer of type EfiBootServicesData.
450 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the
451 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a
452 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the
453 request, then NULL is returned.
455 @param AllocationSize The number of bytes to allocate and zero.
457 @return A pointer to the allocated buffer or NULL if allocation fails.
463 IN UINTN AllocationSize
468 Memory
= AllocatePool (AllocationSize
);
469 if (Memory
!= NULL
) {
470 Memory
= ZeroMem (Memory
, AllocationSize
);
476 Allocates and zeros a buffer of type EfiRuntimeServicesData.
478 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, clears the
479 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a
480 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the
481 request, then NULL is returned.
483 @param AllocationSize The number of bytes to allocate and zero.
485 @return A pointer to the allocated buffer or NULL if allocation fails.
490 AllocateRuntimeZeroPool (
491 IN UINTN AllocationSize
494 return InternalAllocateZeroPool (EfiRuntimeServicesData
, AllocationSize
);
498 Allocates and zeros a buffer of type EfiReservedMemoryType.
500 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, clears the
501 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a
502 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the
503 request, then NULL is returned.
505 @param AllocationSize The number of bytes to allocate and zero.
507 @return A pointer to the allocated buffer or NULL if allocation fails.
512 AllocateReservedZeroPool (
513 IN UINTN AllocationSize
516 return InternalAllocateZeroPool (EfiReservedMemoryType
, AllocationSize
);
520 Copies a buffer to an allocated buffer of a certain pool type.
522 Allocates the number bytes specified by AllocationSize of a certain pool type, copies
523 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
524 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there
525 is not enough memory remaining to satisfy the request, then NULL is returned.
526 If Buffer is NULL, then ASSERT().
527 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
529 @param PoolType The type of pool to allocate.
530 @param AllocationSize The number of bytes to allocate and zero.
531 @param Buffer The buffer to copy to the allocated buffer.
533 @return A pointer to the allocated buffer or NULL if allocation fails.
537 InternalAllocateCopyPool (
538 IN EFI_MEMORY_TYPE PoolType
,
539 IN UINTN AllocationSize
,
540 IN CONST VOID
*Buffer
545 ASSERT (Buffer
!= NULL
);
546 ASSERT (AllocationSize
<= (MAX_ADDRESS
- (UINTN
) Buffer
+ 1));
548 Memory
= InternalAllocatePool (PoolType
, AllocationSize
);
549 if (Memory
!= NULL
) {
550 Memory
= CopyMem (Memory
, Buffer
, AllocationSize
);
556 Copies a buffer to an allocated buffer of type EfiBootServicesData.
558 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, copies
559 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
560 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there
561 is not enough memory remaining to satisfy the request, then NULL is returned.
563 If Buffer is NULL, then ASSERT().
564 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
566 @param AllocationSize The number of bytes to allocate and zero.
567 @param Buffer The buffer to copy to the allocated buffer.
569 @return A pointer to the allocated buffer or NULL if allocation fails.
575 IN UINTN AllocationSize
,
576 IN CONST VOID
*Buffer
581 ASSERT (Buffer
!= NULL
);
582 ASSERT (AllocationSize
<= (MAX_ADDRESS
- (UINTN
) Buffer
+ 1));
584 Memory
= AllocatePool (AllocationSize
);
585 if (Memory
!= NULL
) {
586 Memory
= CopyMem (Memory
, Buffer
, AllocationSize
);
592 Copies a buffer to an allocated buffer of type EfiRuntimeServicesData.
594 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, copies
595 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
596 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there
597 is not enough memory remaining to satisfy the request, then NULL is returned.
599 If Buffer is NULL, then ASSERT().
600 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
602 @param AllocationSize The number of bytes to allocate and zero.
603 @param Buffer The buffer to copy to the allocated buffer.
605 @return A pointer to the allocated buffer or NULL if allocation fails.
610 AllocateRuntimeCopyPool (
611 IN UINTN AllocationSize
,
612 IN CONST VOID
*Buffer
615 return InternalAllocateCopyPool (EfiRuntimeServicesData
, AllocationSize
, Buffer
);
619 Copies a buffer to an allocated buffer of type EfiReservedMemoryType.
621 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, copies
622 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
623 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there
624 is not enough memory remaining to satisfy the request, then NULL is returned.
626 If Buffer is NULL, then ASSERT().
627 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
629 @param AllocationSize The number of bytes to allocate and zero.
630 @param Buffer The buffer to copy to the allocated buffer.
632 @return A pointer to the allocated buffer or NULL if allocation fails.
637 AllocateReservedCopyPool (
638 IN UINTN AllocationSize
,
639 IN CONST VOID
*Buffer
642 return InternalAllocateCopyPool (EfiReservedMemoryType
, AllocationSize
, Buffer
);
646 Reallocates a buffer of a specified memory type.
648 Allocates and zeros the number bytes specified by NewSize from memory of the type
649 specified by PoolType. If OldBuffer is not NULL, then the smaller of OldSize and
650 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
651 OldBuffer is freed. A pointer to the newly allocated buffer is returned.
652 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not
653 enough memory remaining to satisfy the request, then NULL is returned.
655 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
656 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
658 @param PoolType The type of pool to allocate.
659 @param OldSize The size, in bytes, of OldBuffer.
660 @param NewSize The size, in bytes, of the buffer to reallocate.
661 @param OldBuffer The buffer to copy to the allocated buffer. This is an
662 optional parameter that may be NULL.
664 @return A pointer to the allocated buffer or NULL if allocation fails.
668 InternalReallocatePool (
669 IN EFI_MEMORY_TYPE PoolType
,
672 IN VOID
*OldBuffer OPTIONAL
677 NewBuffer
= InternalAllocateZeroPool (PoolType
, NewSize
);
678 if (NewBuffer
!= NULL
&& OldBuffer
!= NULL
) {
679 CopyMem (NewBuffer
, OldBuffer
, MIN (OldSize
, NewSize
));
680 FreePool (OldBuffer
);
686 Reallocates a buffer of type EfiBootServicesData.
688 Allocates and zeros the number bytes specified by NewSize from memory of type
689 EfiBootServicesData. If OldBuffer is not NULL, then the smaller of OldSize and
690 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
691 OldBuffer is freed. A pointer to the newly allocated buffer is returned.
692 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not
693 enough memory remaining to satisfy the request, then NULL is returned.
695 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
696 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
698 @param OldSize The size, in bytes, of OldBuffer.
699 @param NewSize The size, in bytes, of the buffer to reallocate.
700 @param OldBuffer The buffer to copy to the allocated buffer. This is an optional
701 parameter that may be NULL.
703 @return A pointer to the allocated buffer or NULL if allocation fails.
711 IN VOID
*OldBuffer OPTIONAL
714 return InternalReallocatePool (EfiBootServicesData
, OldSize
, NewSize
, OldBuffer
);
718 Reallocates a buffer of type EfiRuntimeServicesData.
720 Allocates and zeros the number bytes specified by NewSize from memory of type
721 EfiRuntimeServicesData. If OldBuffer is not NULL, then the smaller of OldSize and
722 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
723 OldBuffer is freed. A pointer to the newly allocated buffer is returned.
724 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not
725 enough memory remaining to satisfy the request, then NULL is returned.
727 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
728 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
730 @param OldSize The size, in bytes, of OldBuffer.
731 @param NewSize The size, in bytes, of the buffer to reallocate.
732 @param OldBuffer The buffer to copy to the allocated buffer. This is an optional
733 parameter that may be NULL.
735 @return A pointer to the allocated buffer or NULL if allocation fails.
740 ReallocateRuntimePool (
743 IN VOID
*OldBuffer OPTIONAL
746 return InternalReallocatePool (EfiRuntimeServicesData
, OldSize
, NewSize
, OldBuffer
);
750 Reallocates a buffer of type EfiReservedMemoryType.
752 Allocates and zeros the number bytes specified by NewSize from memory of type
753 EfiReservedMemoryType. If OldBuffer is not NULL, then the smaller of OldSize and
754 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
755 OldBuffer is freed. A pointer to the newly allocated buffer is returned.
756 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not
757 enough memory remaining to satisfy the request, then NULL is returned.
759 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
760 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
762 @param OldSize The size, in bytes, of OldBuffer.
763 @param NewSize The size, in bytes, of the buffer to reallocate.
764 @param OldBuffer The buffer to copy to the allocated buffer. This is an
765 optional parameter that may be NULL.
767 @return A pointer to the allocated buffer or NULL if allocation fails.
772 ReallocateReservedPool (
775 IN VOID
*OldBuffer OPTIONAL
778 return InternalReallocatePool (EfiReservedMemoryType
, OldSize
, NewSize
, OldBuffer
);
782 Frees a buffer that was previously allocated with one of the pool allocation functions in the
783 Memory Allocation Library.
785 Frees the buffer specified by Buffer. Buffer must have been allocated on a previous call to the
786 pool allocation services of the Memory Allocation Library. If it is not possible to free pool
787 resources, then this function will perform no actions.
789 If Buffer was not allocated with a pool allocation function in the Memory Allocation Library,
792 @param Buffer The pointer to the buffer to free.
802 // PEI phase does not support to free pool, so leave it as NOP.