2 Support routines for memory allocation routines based on SMM Core internal functions.
4 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
5 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
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.
17 #include <Library/MemoryAllocationLib.h>
18 #include <Library/BaseMemoryLib.h>
19 #include <Library/DebugLib.h>
20 #include "PiSmmCoreMemoryAllocationServices.h"
23 Allocates one or more 4KB pages of a certain memory type.
25 Allocates the number of 4KB pages of a certain memory type and returns a pointer to the allocated
26 buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL is returned.
27 If there is not enough memory remaining to satisfy the request, then NULL is returned.
29 @param MemoryType The type of memory to allocate.
30 @param Pages The number of 4 KB pages to allocate.
32 @return A pointer to the allocated buffer or NULL if allocation fails.
36 InternalAllocatePages (
37 IN EFI_MEMORY_TYPE MemoryType
,
42 EFI_PHYSICAL_ADDRESS Memory
;
48 Status
= SmmAllocatePages (AllocateAnyPages
, MemoryType
, Pages
, &Memory
);
49 if (EFI_ERROR (Status
)) {
52 return (VOID
*) (UINTN
) Memory
;
56 Allocates one or more 4KB pages of type EfiBootServicesData.
58 Allocates the number of 4KB pages of type EfiBootServicesData and returns a pointer to the
59 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL
60 is returned. If there is not enough memory remaining to satisfy the request, then NULL is
63 @param Pages The number of 4 KB pages to allocate.
65 @return A pointer to the allocated buffer or NULL if allocation fails.
74 return InternalAllocatePages (EfiRuntimeServicesData
, Pages
);
78 Allocates one or more 4KB pages of type EfiRuntimeServicesData.
80 Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the
81 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL
82 is returned. If there is not enough memory remaining to satisfy the request, then NULL is
85 @param Pages The number of 4 KB pages to allocate.
87 @return A pointer to the allocated buffer or NULL if allocation fails.
92 AllocateRuntimePages (
96 return InternalAllocatePages (EfiRuntimeServicesData
, Pages
);
100 Allocates one or more 4KB pages of type EfiReservedMemoryType.
102 Allocates the number of 4KB pages of type EfiReservedMemoryType and returns a pointer to the
103 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL
104 is returned. If there is not enough memory remaining to satisfy the request, then NULL is
107 @param Pages The number of 4 KB pages to allocate.
109 @return A pointer to the allocated buffer or NULL if allocation fails.
114 AllocateReservedPages (
122 Frees one or more 4KB pages that were previously allocated with one of the page allocation
123 functions in the Memory Allocation Library.
125 Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer
126 must have been allocated on a previous call to the page allocation services of the Memory
127 Allocation Library. If it is not possible to free allocated pages, then this function will
130 If Buffer was not allocated with a page allocation function in the Memory Allocation Library,
132 If Pages is zero, then ASSERT().
134 @param Buffer Pointer to the buffer of pages to free.
135 @param Pages The number of 4 KB pages to free.
148 Status
= SmmFreePages ((EFI_PHYSICAL_ADDRESS
) (UINTN
) Buffer
, Pages
);
149 ASSERT_EFI_ERROR (Status
);
153 Allocates one or more 4KB pages of a certain memory type at a specified alignment.
155 Allocates the number of 4KB pages specified by Pages of a certain memory type with an alignment
156 specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is returned.
157 If there is not enough memory at the specified alignment remaining to satisfy the request, then
159 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
161 @param MemoryType The type of memory to allocate.
162 @param Pages The number of 4 KB pages to allocate.
163 @param Alignment The requested alignment of the allocation. Must be a power of two.
164 If Alignment is zero, then byte alignment is used.
166 @return A pointer to the allocated buffer or NULL if allocation fails.
170 InternalAllocateAlignedPages (
171 IN EFI_MEMORY_TYPE MemoryType
,
177 EFI_PHYSICAL_ADDRESS Memory
;
180 UINTN UnalignedPages
;
184 // Alignment must be a power of two or zero.
186 ASSERT ((Alignment
& (Alignment
- 1)) == 0);
191 if (Alignment
> EFI_PAGE_SIZE
) {
193 // Caculate the total number of pages since alignment is larger than page size.
195 AlignmentMask
= Alignment
- 1;
196 RealPages
= Pages
+ EFI_SIZE_TO_PAGES (Alignment
);
198 // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
200 ASSERT (RealPages
> Pages
);
202 Status
= SmmAllocatePages (AllocateAnyPages
, MemoryType
, RealPages
, &Memory
);
203 if (EFI_ERROR (Status
)) {
206 AlignedMemory
= ((UINTN
) Memory
+ AlignmentMask
) & ~AlignmentMask
;
207 UnalignedPages
= EFI_SIZE_TO_PAGES (AlignedMemory
- (UINTN
) Memory
);
208 if (UnalignedPages
> 0) {
210 // Free first unaligned page(s).
212 Status
= SmmFreePages (Memory
, UnalignedPages
);
213 ASSERT_EFI_ERROR (Status
);
215 Memory
= (EFI_PHYSICAL_ADDRESS
) (AlignedMemory
+ EFI_PAGES_TO_SIZE (Pages
));
216 UnalignedPages
= RealPages
- Pages
- UnalignedPages
;
217 if (UnalignedPages
> 0) {
219 // Free last unaligned page(s).
221 Status
= SmmFreePages (Memory
, UnalignedPages
);
222 ASSERT_EFI_ERROR (Status
);
226 // Do not over-allocate pages in this case.
228 Status
= SmmAllocatePages (AllocateAnyPages
, MemoryType
, Pages
, &Memory
);
229 if (EFI_ERROR (Status
)) {
232 AlignedMemory
= (UINTN
) Memory
;
234 return (VOID
*) AlignedMemory
;
238 Allocates one or more 4KB pages of type EfiBootServicesData at a specified alignment.
240 Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData with an
241 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is
242 returned. If there is not enough memory at the specified alignment remaining to satisfy the
243 request, then NULL is returned.
245 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
247 @param Pages The number of 4 KB pages to allocate.
248 @param Alignment The requested alignment of the allocation. Must be a power of two.
249 If Alignment is zero, then byte alignment is used.
251 @return A pointer to the allocated buffer or NULL if allocation fails.
256 AllocateAlignedPages (
261 return InternalAllocateAlignedPages (EfiRuntimeServicesData
, Pages
, Alignment
);
265 Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment.
267 Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData with an
268 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is
269 returned. If there is not enough memory at the specified alignment remaining to satisfy the
270 request, then NULL is returned.
272 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
274 @param Pages The number of 4 KB pages to allocate.
275 @param Alignment The requested alignment of the allocation. 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 AllocateAlignedRuntimePages (
288 return InternalAllocateAlignedPages (EfiRuntimeServicesData
, Pages
, Alignment
);
292 Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment.
294 Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType with an
295 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is
296 returned. If there is not enough memory at the specified alignment remaining to satisfy the
297 request, then NULL is returned.
299 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
301 @param Pages The number of 4 KB pages to allocate.
302 @param Alignment The requested alignment of the allocation. Must be a power of two.
303 If Alignment is zero, then byte alignment is used.
305 @return A pointer to the allocated buffer or NULL if allocation fails.
310 AllocateAlignedReservedPages (
319 Frees one or more 4KB pages that were previously allocated with one of the aligned page
320 allocation functions in the Memory Allocation Library.
322 Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer
323 must have been allocated on a previous call to the aligned page allocation services of the Memory
324 Allocation Library. If it is not possible to free allocated pages, then this function will
327 If Buffer was not allocated with an aligned page allocation function in the Memory Allocation
328 Library, then ASSERT().
329 If Pages is zero, then ASSERT().
331 @param Buffer Pointer to the buffer of pages to free.
332 @param Pages The number of 4 KB pages to free.
345 Status
= SmmFreePages ((EFI_PHYSICAL_ADDRESS
) (UINTN
) Buffer
, Pages
);
346 ASSERT_EFI_ERROR (Status
);
350 Allocates a buffer of a certain pool type.
352 Allocates the number bytes specified by AllocationSize of a certain pool type and returns a
353 pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
354 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
356 @param MemoryType The type of memory to allocate.
357 @param AllocationSize The number of bytes to allocate.
359 @return A pointer to the allocated buffer or NULL if allocation fails.
363 InternalAllocatePool (
364 IN EFI_MEMORY_TYPE MemoryType
,
365 IN UINTN AllocationSize
371 Status
= SmmAllocatePool (MemoryType
, AllocationSize
, &Memory
);
372 if (EFI_ERROR (Status
)) {
379 Allocates a buffer of type EfiBootServicesData.
381 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a
382 pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
383 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
385 @param AllocationSize The number of bytes to allocate.
387 @return A pointer to the allocated buffer or NULL if allocation fails.
393 IN UINTN AllocationSize
396 return InternalAllocatePool (EfiRuntimeServicesData
, AllocationSize
);
400 Allocates a buffer of type EfiRuntimeServicesData.
402 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData and returns
403 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
404 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
406 @param AllocationSize The number of bytes to allocate.
408 @return A pointer to the allocated buffer or NULL if allocation fails.
413 AllocateRuntimePool (
414 IN UINTN AllocationSize
417 return InternalAllocatePool (EfiRuntimeServicesData
, AllocationSize
);
421 Allocates a buffer of type EfiReservedMemoryType.
423 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType and returns
424 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
425 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
427 @param AllocationSize The number of bytes to allocate.
429 @return A pointer to the allocated buffer or NULL if allocation fails.
434 AllocateReservedPool (
435 IN UINTN AllocationSize
442 Allocates and zeros a buffer of a certain pool type.
444 Allocates the number bytes specified by AllocationSize of a certain pool type, clears the buffer
445 with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a valid
446 buffer of 0 size is returned. If there is not enough memory remaining to satisfy the request,
447 then NULL is returned.
449 @param PoolType The type of memory to allocate.
450 @param AllocationSize The number of bytes to allocate and zero.
452 @return A pointer to the allocated buffer or NULL if allocation fails.
456 InternalAllocateZeroPool (
457 IN EFI_MEMORY_TYPE PoolType
,
458 IN UINTN AllocationSize
463 Memory
= InternalAllocatePool (PoolType
, AllocationSize
);
464 if (Memory
!= NULL
) {
465 Memory
= ZeroMem (Memory
, AllocationSize
);
471 Allocates and zeros a buffer of type EfiBootServicesData.
473 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the
474 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a
475 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the
476 request, then NULL is returned.
478 @param AllocationSize The number of bytes to allocate and zero.
480 @return A pointer to the allocated buffer or NULL if allocation fails.
486 IN UINTN AllocationSize
489 return InternalAllocateZeroPool (EfiRuntimeServicesData
, AllocationSize
);
493 Allocates and zeros a buffer of type EfiRuntimeServicesData.
495 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, clears the
496 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a
497 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the
498 request, then NULL is returned.
500 @param AllocationSize The number of bytes to allocate and zero.
502 @return A pointer to the allocated buffer or NULL if allocation fails.
507 AllocateRuntimeZeroPool (
508 IN UINTN AllocationSize
511 return InternalAllocateZeroPool (EfiRuntimeServicesData
, AllocationSize
);
515 Allocates and zeros a buffer of type EfiReservedMemoryType.
517 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, clears the
518 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a
519 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the
520 request, then NULL is returned.
522 @param AllocationSize The number of bytes to allocate and zero.
524 @return A pointer to the allocated buffer or NULL if allocation fails.
529 AllocateReservedZeroPool (
530 IN UINTN AllocationSize
537 Copies a buffer to an allocated buffer of a certain pool type.
539 Allocates the number bytes specified by AllocationSize of a certain pool type, copies
540 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
541 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there
542 is not enough memory remaining to satisfy the request, then NULL is returned.
543 If Buffer is NULL, then ASSERT().
544 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
546 @param PoolType The type of pool to allocate.
547 @param AllocationSize The number of bytes to allocate and zero.
548 @param Buffer The buffer to copy to the allocated buffer.
550 @return A pointer to the allocated buffer or NULL if allocation fails.
554 InternalAllocateCopyPool (
555 IN EFI_MEMORY_TYPE PoolType
,
556 IN UINTN AllocationSize
,
557 IN CONST VOID
*Buffer
562 ASSERT (Buffer
!= NULL
);
563 ASSERT (AllocationSize
<= (MAX_ADDRESS
- (UINTN
) Buffer
+ 1));
565 Memory
= InternalAllocatePool (PoolType
, AllocationSize
);
566 if (Memory
!= NULL
) {
567 Memory
= CopyMem (Memory
, Buffer
, AllocationSize
);
573 Copies a buffer to an allocated buffer of type EfiBootServicesData.
575 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, copies
576 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
577 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there
578 is not enough memory remaining to satisfy the request, then NULL is returned.
580 If Buffer is NULL, then ASSERT().
581 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
583 @param AllocationSize The number of bytes to allocate and zero.
584 @param Buffer The buffer to copy to the allocated buffer.
586 @return A pointer to the allocated buffer or NULL if allocation fails.
592 IN UINTN AllocationSize
,
593 IN CONST VOID
*Buffer
596 return InternalAllocateCopyPool (EfiRuntimeServicesData
, AllocationSize
, Buffer
);
600 Copies a buffer to an allocated buffer of type EfiRuntimeServicesData.
602 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, copies
603 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
604 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there
605 is not enough memory remaining to satisfy the request, then NULL is returned.
607 If Buffer is NULL, then ASSERT().
608 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
610 @param AllocationSize The number of bytes to allocate and zero.
611 @param Buffer The buffer to copy to the allocated buffer.
613 @return A pointer to the allocated buffer or NULL if allocation fails.
618 AllocateRuntimeCopyPool (
619 IN UINTN AllocationSize
,
620 IN CONST VOID
*Buffer
623 return InternalAllocateCopyPool (EfiRuntimeServicesData
, AllocationSize
, Buffer
);
627 Copies a buffer to an allocated buffer of type EfiReservedMemoryType.
629 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, copies
630 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
631 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there
632 is not enough memory remaining to satisfy the request, then NULL is returned.
634 If Buffer is NULL, then ASSERT().
635 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
637 @param AllocationSize The number of bytes to allocate and zero.
638 @param Buffer The buffer to copy to the allocated buffer.
640 @return A pointer to the allocated buffer or NULL if allocation fails.
645 AllocateReservedCopyPool (
646 IN UINTN AllocationSize
,
647 IN CONST VOID
*Buffer
654 Reallocates a buffer of a specified memory type.
656 Allocates and zeros the number bytes specified by NewSize from memory of the type
657 specified by PoolType. If OldBuffer is not NULL, then the smaller of OldSize and
658 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
659 OldBuffer is freed. A pointer to the newly allocated buffer is returned.
660 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not
661 enough memory remaining to satisfy the request, then NULL is returned.
663 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
664 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
666 @param PoolType The type of pool to allocate.
667 @param OldSize The size, in bytes, of OldBuffer.
668 @param NewSize The size, in bytes, of the buffer to reallocate.
669 @param OldBuffer The buffer to copy to the allocated buffer. This is an optional
670 parameter that may be NULL.
672 @return A pointer to the allocated buffer or NULL if allocation fails.
676 InternalReallocatePool (
677 IN EFI_MEMORY_TYPE PoolType
,
680 IN VOID
*OldBuffer OPTIONAL
685 NewBuffer
= InternalAllocateZeroPool (PoolType
, NewSize
);
686 if (NewBuffer
!= NULL
&& OldBuffer
!= NULL
) {
687 CopyMem (NewBuffer
, OldBuffer
, MIN (OldSize
, NewSize
));
688 FreePool (OldBuffer
);
694 Reallocates a buffer of type EfiBootServicesData.
696 Allocates and zeros the number bytes specified by NewSize from memory of type
697 EfiBootServicesData. If OldBuffer is not NULL, then the smaller of OldSize and
698 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
699 OldBuffer is freed. A pointer to the newly allocated buffer is returned.
700 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not
701 enough memory remaining to satisfy the request, then NULL is returned.
703 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
704 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
706 @param OldSize The size, in bytes, of OldBuffer.
707 @param NewSize The size, in bytes, of the buffer to reallocate.
708 @param OldBuffer The buffer to copy to the allocated buffer. This is an optional
709 parameter that may be NULL.
711 @return A pointer to the allocated buffer or NULL if allocation fails.
719 IN VOID
*OldBuffer OPTIONAL
722 return InternalReallocatePool (EfiRuntimeServicesData
, OldSize
, NewSize
, OldBuffer
);
726 Reallocates a buffer of type EfiRuntimeServicesData.
728 Allocates and zeros the number bytes specified by NewSize from memory of type
729 EfiRuntimeServicesData. If OldBuffer is not NULL, then the smaller of OldSize and
730 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
731 OldBuffer is freed. A pointer to the newly allocated buffer is returned.
732 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not
733 enough memory remaining to satisfy the request, then NULL is returned.
735 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
736 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
738 @param OldSize The size, in bytes, of OldBuffer.
739 @param NewSize The size, in bytes, of the buffer to reallocate.
740 @param OldBuffer The buffer to copy to the allocated buffer. This is an optional
741 parameter that may be NULL.
743 @return A pointer to the allocated buffer or NULL if allocation fails.
748 ReallocateRuntimePool (
751 IN VOID
*OldBuffer OPTIONAL
754 return InternalReallocatePool (EfiRuntimeServicesData
, OldSize
, NewSize
, OldBuffer
);
758 Reallocates a buffer of type EfiReservedMemoryType.
760 Allocates and zeros the number bytes specified by NewSize from memory of type
761 EfiReservedMemoryType. If OldBuffer is not NULL, then the smaller of OldSize and
762 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
763 OldBuffer is freed. A pointer to the newly allocated buffer is returned.
764 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not
765 enough memory remaining to satisfy the request, then NULL is returned.
767 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
768 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
770 @param OldSize The size, in bytes, of OldBuffer.
771 @param NewSize The size, in bytes, of the buffer to reallocate.
772 @param OldBuffer The buffer to copy to the allocated buffer. This is an optional
773 parameter that may be NULL.
775 @return A pointer to the allocated buffer or NULL if allocation fails.
780 ReallocateReservedPool (
783 IN VOID
*OldBuffer OPTIONAL
790 Frees a buffer that was previously allocated with one of the pool allocation functions in the
791 Memory Allocation Library.
793 Frees the buffer specified by Buffer. Buffer must have been allocated on a previous call to the
794 pool allocation services of the Memory Allocation Library. If it is not possible to free pool
795 resources, then this function will perform no actions.
797 If Buffer was not allocated with a pool allocation function in the Memory Allocation Library,
800 @param Buffer Pointer to the buffer to free.
811 Status
= SmmFreePool (Buffer
);
812 ASSERT_EFI_ERROR (Status
);