2 Support routines for memory allocation routines based on SMM Core internal functions,
3 with memory profile support.
5 The PI System Management Mode Core Interface Specification only allows the use
6 of EfiRuntimeServicesCode and EfiRuntimeServicesData memory types for memory
7 allocations as the SMRAM space should be reserved after BDS phase. The functions
8 in the Memory Allocation Library use EfiBootServicesData as the default memory
9 allocation type. For this SMM specific instance of the Memory Allocation Library,
10 EfiRuntimeServicesData is used as the default memory type for all allocations.
11 In addition, allocation for the Reserved memory types are not supported and will
14 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
15 SPDX-License-Identifier: BSD-2-Clause-Patent
21 #include <Library/MemoryAllocationLib.h>
22 #include <Library/UefiBootServicesTableLib.h>
23 #include <Library/BaseMemoryLib.h>
24 #include <Library/DebugLib.h>
25 #include "PiSmmCoreMemoryAllocationServices.h"
27 #include <Library/MemoryProfileLib.h>
29 EFI_SMRAM_DESCRIPTOR
*mSmmCoreMemoryAllocLibSmramRanges
= NULL
;
30 UINTN mSmmCoreMemoryAllocLibSmramRangeCount
= 0;
33 Check whether the start address of buffer is within any of the SMRAM ranges.
35 @param[in] Buffer The pointer to the buffer to be checked.
37 @retval TRUE The buffer is in SMRAM ranges.
38 @retval FALSE The buffer is out of SMRAM ranges.
48 for (Index
= 0; Index
< mSmmCoreMemoryAllocLibSmramRangeCount
; Index
++) {
49 if (((EFI_PHYSICAL_ADDRESS
) (UINTN
) Buffer
>= mSmmCoreMemoryAllocLibSmramRanges
[Index
].CpuStart
) &&
50 ((EFI_PHYSICAL_ADDRESS
) (UINTN
) Buffer
< (mSmmCoreMemoryAllocLibSmramRanges
[Index
].CpuStart
+ mSmmCoreMemoryAllocLibSmramRanges
[Index
].PhysicalSize
))) {
59 Allocates one or more 4KB pages of a certain memory type.
61 Allocates the number of 4KB pages of a certain memory type and returns a pointer to the allocated
62 buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL is returned.
63 If there is not enough memory remaining to satisfy the request, then NULL is returned.
65 @param MemoryType The type of memory to allocate.
66 @param Pages The number of 4 KB pages to allocate.
68 @return A pointer to the allocated buffer or NULL if allocation fails.
72 InternalAllocatePages (
73 IN EFI_MEMORY_TYPE MemoryType
,
78 EFI_PHYSICAL_ADDRESS Memory
;
84 Status
= SmmAllocatePages (AllocateAnyPages
, MemoryType
, Pages
, &Memory
);
85 if (EFI_ERROR (Status
)) {
88 return (VOID
*) (UINTN
) Memory
;
92 Allocates one or more 4KB pages of type EfiRuntimeServicesData.
94 Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the
95 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL
96 is returned. If there is not enough memory remaining to satisfy the request, then NULL is
99 @param Pages The number of 4 KB pages to allocate.
101 @return A pointer to the allocated buffer or NULL if allocation fails.
112 Buffer
= InternalAllocatePages (EfiRuntimeServicesData
, Pages
);
113 if (Buffer
!= NULL
) {
114 MemoryProfileLibRecord (
115 (PHYSICAL_ADDRESS
) (UINTN
) RETURN_ADDRESS(0),
116 MEMORY_PROFILE_ACTION_LIB_ALLOCATE_PAGES
,
117 EfiRuntimeServicesData
,
119 EFI_PAGES_TO_SIZE(Pages
),
127 Allocates one or more 4KB pages of type EfiRuntimeServicesData.
129 Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the
130 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL
131 is returned. If there is not enough memory remaining to satisfy the request, then NULL is
134 @param Pages The number of 4 KB pages to allocate.
136 @return A pointer to the allocated buffer or NULL if allocation fails.
141 AllocateRuntimePages (
147 Buffer
= InternalAllocatePages (EfiRuntimeServicesData
, Pages
);
148 if (Buffer
!= NULL
) {
149 MemoryProfileLibRecord (
150 (PHYSICAL_ADDRESS
) (UINTN
) RETURN_ADDRESS(0),
151 MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_PAGES
,
152 EfiRuntimeServicesData
,
154 EFI_PAGES_TO_SIZE(Pages
),
162 Allocates one or more 4KB pages of type EfiReservedMemoryType.
164 Allocates the number of 4KB pages of type EfiReservedMemoryType and returns a pointer to the
165 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL
166 is returned. If there is not enough memory remaining to satisfy the request, then NULL is
169 @param Pages The number of 4 KB pages to allocate.
171 @return A pointer to the allocated buffer or NULL if allocation fails.
176 AllocateReservedPages (
184 Frees one or more 4KB pages that were previously allocated with one of the page allocation
185 functions in the Memory Allocation Library.
187 Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer
188 must have been allocated on a previous call to the page allocation services of the Memory
189 Allocation Library. If it is not possible to free allocated pages, then this function will
192 If Buffer was not allocated with a page allocation function in the Memory Allocation Library,
194 If Pages is zero, then ASSERT().
196 @param Buffer Pointer to the buffer of pages to free.
197 @param Pages The number of 4 KB pages to free.
210 if (BufferInSmram (Buffer
)) {
212 // When Buffer is in SMRAM range, it should be allocated by SmmAllocatePages() service.
213 // So, SmmFreePages() service is used to free it.
215 Status
= SmmFreePages ((EFI_PHYSICAL_ADDRESS
) (UINTN
) Buffer
, Pages
);
218 // When Buffer is out of SMRAM range, it should be allocated by gBS->AllocatePages() service.
219 // So, gBS->FreePages() service is used to free it.
221 Status
= gBS
->FreePages ((EFI_PHYSICAL_ADDRESS
) (UINTN
) Buffer
, Pages
);
223 ASSERT_EFI_ERROR (Status
);
227 Allocates one or more 4KB pages of a certain memory type at a specified alignment.
229 Allocates the number of 4KB pages specified by Pages of a certain memory type with an alignment
230 specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is returned.
231 If there is not enough memory at the specified alignment remaining to satisfy the request, then
233 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
234 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
236 @param MemoryType The type of memory to allocate.
237 @param Pages The number of 4 KB pages to allocate.
238 @param Alignment The requested alignment of the allocation. Must be a power of two.
239 If Alignment is zero, then byte alignment is used.
241 @return A pointer to the allocated buffer or NULL if allocation fails.
245 InternalAllocateAlignedPages (
246 IN EFI_MEMORY_TYPE MemoryType
,
252 EFI_PHYSICAL_ADDRESS Memory
;
255 UINTN UnalignedPages
;
259 // Alignment must be a power of two or zero.
261 ASSERT ((Alignment
& (Alignment
- 1)) == 0);
266 if (Alignment
> EFI_PAGE_SIZE
) {
268 // Calculate the total number of pages since alignment is larger than page size.
270 AlignmentMask
= Alignment
- 1;
271 RealPages
= Pages
+ EFI_SIZE_TO_PAGES (Alignment
);
273 // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
275 ASSERT (RealPages
> Pages
);
277 Status
= SmmAllocatePages (AllocateAnyPages
, MemoryType
, RealPages
, &Memory
);
278 if (EFI_ERROR (Status
)) {
281 AlignedMemory
= ((UINTN
) Memory
+ AlignmentMask
) & ~AlignmentMask
;
282 UnalignedPages
= EFI_SIZE_TO_PAGES (AlignedMemory
- (UINTN
) Memory
);
283 if (UnalignedPages
> 0) {
285 // Free first unaligned page(s).
287 Status
= SmmFreePages (Memory
, UnalignedPages
);
288 ASSERT_EFI_ERROR (Status
);
290 Memory
= AlignedMemory
+ EFI_PAGES_TO_SIZE (Pages
);
291 UnalignedPages
= RealPages
- Pages
- UnalignedPages
;
292 if (UnalignedPages
> 0) {
294 // Free last unaligned page(s).
296 Status
= SmmFreePages (Memory
, UnalignedPages
);
297 ASSERT_EFI_ERROR (Status
);
301 // Do not over-allocate pages in this case.
303 Status
= SmmAllocatePages (AllocateAnyPages
, MemoryType
, Pages
, &Memory
);
304 if (EFI_ERROR (Status
)) {
307 AlignedMemory
= (UINTN
) Memory
;
309 return (VOID
*) AlignedMemory
;
313 Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment.
315 Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData with an
316 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is
317 returned. If there is not enough memory at the specified alignment remaining to satisfy the
318 request, then NULL is returned.
320 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
321 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
323 @param Pages The number of 4 KB pages to allocate.
324 @param Alignment The requested alignment of the allocation. Must be a power of two.
325 If Alignment is zero, then byte alignment is used.
327 @return A pointer to the allocated buffer or NULL if allocation fails.
332 AllocateAlignedPages (
339 Buffer
= InternalAllocateAlignedPages (EfiRuntimeServicesData
, Pages
, Alignment
);
340 if (Buffer
!= NULL
) {
341 MemoryProfileLibRecord (
342 (PHYSICAL_ADDRESS
) (UINTN
) RETURN_ADDRESS(0),
343 MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_PAGES
,
344 EfiRuntimeServicesData
,
346 EFI_PAGES_TO_SIZE(Pages
),
354 Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment.
356 Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData with an
357 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is
358 returned. If there is not enough memory at the specified alignment remaining to satisfy the
359 request, then NULL is returned.
361 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
362 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
364 @param Pages The number of 4 KB pages to allocate.
365 @param Alignment The requested alignment of the allocation. Must be a power of two.
366 If Alignment is zero, then byte alignment is used.
368 @return A pointer to the allocated buffer or NULL if allocation fails.
373 AllocateAlignedRuntimePages (
380 Buffer
= InternalAllocateAlignedPages (EfiRuntimeServicesData
, Pages
, Alignment
);
381 if (Buffer
!= NULL
) {
382 MemoryProfileLibRecord (
383 (PHYSICAL_ADDRESS
) (UINTN
) RETURN_ADDRESS(0),
384 MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RUNTIME_PAGES
,
385 EfiRuntimeServicesData
,
387 EFI_PAGES_TO_SIZE(Pages
),
395 Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment.
397 Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType with an
398 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is
399 returned. If there is not enough memory at the specified alignment remaining to satisfy the
400 request, then NULL is returned.
402 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
403 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
405 @param Pages The number of 4 KB pages to allocate.
406 @param Alignment The requested alignment of the allocation. Must be a power of two.
407 If Alignment is zero, then byte alignment is used.
409 @return A pointer to the allocated buffer or NULL if allocation fails.
414 AllocateAlignedReservedPages (
423 Frees one or more 4KB pages that were previously allocated with one of the aligned page
424 allocation functions in the Memory Allocation Library.
426 Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer
427 must have been allocated on a previous call to the aligned page allocation services of the Memory
428 Allocation Library. If it is not possible to free allocated pages, then this function will
431 If Buffer was not allocated with an aligned page allocation function in the Memory Allocation
432 Library, then ASSERT().
433 If Pages is zero, then ASSERT().
435 @param Buffer Pointer to the buffer of pages to free.
436 @param Pages The number of 4 KB pages to free.
449 if (BufferInSmram (Buffer
)) {
451 // When Buffer is in SMRAM range, it should be allocated by SmmAllocatePages() service.
452 // So, SmmFreePages() service is used to free it.
454 Status
= SmmFreePages ((EFI_PHYSICAL_ADDRESS
) (UINTN
) Buffer
, Pages
);
457 // When Buffer is out of SMRAM range, it should be allocated by gBS->AllocatePages() service.
458 // So, gBS->FreePages() service is used to free it.
460 Status
= gBS
->FreePages ((EFI_PHYSICAL_ADDRESS
) (UINTN
) Buffer
, Pages
);
462 ASSERT_EFI_ERROR (Status
);
466 Allocates a buffer of a certain pool type.
468 Allocates the number bytes specified by AllocationSize of a certain pool type and returns a
469 pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
470 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
472 @param MemoryType The type of memory to allocate.
473 @param AllocationSize The number of bytes to allocate.
475 @return A pointer to the allocated buffer or NULL if allocation fails.
479 InternalAllocatePool (
480 IN EFI_MEMORY_TYPE MemoryType
,
481 IN UINTN AllocationSize
489 Status
= SmmAllocatePool (MemoryType
, AllocationSize
, &Memory
);
490 if (EFI_ERROR (Status
)) {
497 Allocates a buffer of type EfiRuntimeServicesData.
499 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData and returns a
500 pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
501 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
503 @param AllocationSize The number of bytes to allocate.
505 @return A pointer to the allocated buffer or NULL if allocation fails.
511 IN UINTN AllocationSize
516 Buffer
= InternalAllocatePool (EfiRuntimeServicesData
, AllocationSize
);
517 if (Buffer
!= NULL
) {
518 MemoryProfileLibRecord (
519 (PHYSICAL_ADDRESS
) (UINTN
) RETURN_ADDRESS(0),
520 MEMORY_PROFILE_ACTION_LIB_ALLOCATE_POOL
,
521 EfiRuntimeServicesData
,
531 Allocates a buffer of type EfiRuntimeServicesData.
533 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData and returns
534 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
535 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
537 @param AllocationSize The number of bytes to allocate.
539 @return A pointer to the allocated buffer or NULL if allocation fails.
544 AllocateRuntimePool (
545 IN UINTN AllocationSize
550 Buffer
= InternalAllocatePool (EfiRuntimeServicesData
, AllocationSize
);
551 if (Buffer
!= NULL
) {
552 MemoryProfileLibRecord (
553 (PHYSICAL_ADDRESS
) (UINTN
) RETURN_ADDRESS(0),
554 MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_POOL
,
555 EfiRuntimeServicesData
,
565 Allocates a buffer of type EfiReservedMemoryType.
567 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType and returns
568 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
569 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
571 @param AllocationSize The number of bytes to allocate.
573 @return A pointer to the allocated buffer or NULL if allocation fails.
578 AllocateReservedPool (
579 IN UINTN AllocationSize
586 Allocates and zeros a buffer of a certain pool type.
588 Allocates the number bytes specified by AllocationSize of a certain pool type, clears the buffer
589 with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a valid
590 buffer of 0 size is returned. If there is not enough memory remaining to satisfy the request,
591 then NULL is returned.
593 @param PoolType The type of memory to allocate.
594 @param AllocationSize The number of bytes to allocate and zero.
596 @return A pointer to the allocated buffer or NULL if allocation fails.
600 InternalAllocateZeroPool (
601 IN EFI_MEMORY_TYPE PoolType
,
602 IN UINTN AllocationSize
607 Memory
= InternalAllocatePool (PoolType
, AllocationSize
);
608 if (Memory
!= NULL
) {
609 Memory
= ZeroMem (Memory
, AllocationSize
);
615 Allocates and zeros a buffer of type EfiRuntimeServicesData.
617 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, clears the
618 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a
619 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the
620 request, then NULL is returned.
622 @param AllocationSize The number of bytes to allocate and zero.
624 @return A pointer to the allocated buffer or NULL if allocation fails.
630 IN UINTN AllocationSize
635 Buffer
= InternalAllocateZeroPool (EfiRuntimeServicesData
, AllocationSize
);
636 if (Buffer
!= NULL
) {
637 MemoryProfileLibRecord (
638 (PHYSICAL_ADDRESS
) (UINTN
) RETURN_ADDRESS(0),
639 MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ZERO_POOL
,
640 EfiRuntimeServicesData
,
650 Allocates and zeros a buffer of type EfiRuntimeServicesData.
652 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, clears the
653 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a
654 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the
655 request, then NULL is returned.
657 @param AllocationSize The number of bytes to allocate and zero.
659 @return A pointer to the allocated buffer or NULL if allocation fails.
664 AllocateRuntimeZeroPool (
665 IN UINTN AllocationSize
670 Buffer
= InternalAllocateZeroPool (EfiRuntimeServicesData
, AllocationSize
);
671 if (Buffer
!= NULL
) {
672 MemoryProfileLibRecord (
673 (PHYSICAL_ADDRESS
) (UINTN
) RETURN_ADDRESS(0),
674 MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_ZERO_POOL
,
675 EfiRuntimeServicesData
,
685 Allocates and zeros a buffer of type EfiReservedMemoryType.
687 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, clears the
688 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a
689 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the
690 request, then NULL is returned.
692 @param AllocationSize The number of bytes to allocate and zero.
694 @return A pointer to the allocated buffer or NULL if allocation fails.
699 AllocateReservedZeroPool (
700 IN UINTN AllocationSize
707 Copies a buffer to an allocated buffer of a certain pool type.
709 Allocates the number bytes specified by AllocationSize of a certain pool type, copies
710 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
711 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there
712 is not enough memory remaining to satisfy the request, then NULL is returned.
713 If Buffer is NULL, then ASSERT().
714 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
716 @param PoolType The type of pool to allocate.
717 @param AllocationSize The number of bytes to allocate and zero.
718 @param Buffer The buffer to copy to the allocated buffer.
720 @return A pointer to the allocated buffer or NULL if allocation fails.
724 InternalAllocateCopyPool (
725 IN EFI_MEMORY_TYPE PoolType
,
726 IN UINTN AllocationSize
,
727 IN CONST VOID
*Buffer
732 ASSERT (Buffer
!= NULL
);
733 ASSERT (AllocationSize
<= (MAX_ADDRESS
- (UINTN
) Buffer
+ 1));
735 Memory
= InternalAllocatePool (PoolType
, AllocationSize
);
736 if (Memory
!= NULL
) {
737 Memory
= CopyMem (Memory
, Buffer
, AllocationSize
);
743 Copies a buffer to an allocated buffer of type EfiRuntimeServicesData.
745 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, copies
746 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
747 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there
748 is not enough memory remaining to satisfy the request, then NULL is returned.
750 If Buffer is NULL, then ASSERT().
751 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
753 @param AllocationSize The number of bytes to allocate and zero.
754 @param Buffer The buffer to copy to the allocated buffer.
756 @return A pointer to the allocated buffer or NULL if allocation fails.
762 IN UINTN AllocationSize
,
763 IN CONST VOID
*Buffer
768 NewBuffer
= InternalAllocateCopyPool (EfiRuntimeServicesData
, AllocationSize
, Buffer
);
769 if (NewBuffer
!= NULL
) {
770 MemoryProfileLibRecord (
771 (PHYSICAL_ADDRESS
) (UINTN
) RETURN_ADDRESS(0),
772 MEMORY_PROFILE_ACTION_LIB_ALLOCATE_COPY_POOL
,
773 EfiRuntimeServicesData
,
783 Copies a buffer to an allocated buffer of type EfiRuntimeServicesData.
785 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, copies
786 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
787 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there
788 is not enough memory remaining to satisfy the request, then NULL is returned.
790 If Buffer is NULL, then ASSERT().
791 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
793 @param AllocationSize The number of bytes to allocate and zero.
794 @param Buffer The buffer to copy to the allocated buffer.
796 @return A pointer to the allocated buffer or NULL if allocation fails.
801 AllocateRuntimeCopyPool (
802 IN UINTN AllocationSize
,
803 IN CONST VOID
*Buffer
808 NewBuffer
= InternalAllocateCopyPool (EfiRuntimeServicesData
, AllocationSize
, Buffer
);
809 if (NewBuffer
!= NULL
) {
810 MemoryProfileLibRecord (
811 (PHYSICAL_ADDRESS
) (UINTN
) RETURN_ADDRESS(0),
812 MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_COPY_POOL
,
813 EfiRuntimeServicesData
,
823 Copies a buffer to an allocated buffer of type EfiReservedMemoryType.
825 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, copies
826 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
827 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there
828 is not enough memory remaining to satisfy the request, then NULL is returned.
830 If Buffer is NULL, then ASSERT().
831 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
833 @param AllocationSize The number of bytes to allocate and zero.
834 @param Buffer The buffer to copy to the allocated buffer.
836 @return A pointer to the allocated buffer or NULL if allocation fails.
841 AllocateReservedCopyPool (
842 IN UINTN AllocationSize
,
843 IN CONST VOID
*Buffer
850 Reallocates a buffer of a specified memory type.
852 Allocates and zeros the number bytes specified by NewSize from memory of the type
853 specified by PoolType. If OldBuffer is not NULL, then the smaller of OldSize and
854 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
855 OldBuffer is freed. A pointer to the newly allocated buffer is returned.
856 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not
857 enough memory remaining to satisfy the request, then NULL is returned.
859 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
860 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
862 @param PoolType The type of pool to allocate.
863 @param OldSize The size, in bytes, of OldBuffer.
864 @param NewSize The size, in bytes, of the buffer to reallocate.
865 @param OldBuffer The buffer to copy to the allocated buffer. This is an optional
866 parameter that may be NULL.
868 @return A pointer to the allocated buffer or NULL if allocation fails.
872 InternalReallocatePool (
873 IN EFI_MEMORY_TYPE PoolType
,
876 IN VOID
*OldBuffer OPTIONAL
881 NewBuffer
= InternalAllocateZeroPool (PoolType
, NewSize
);
882 if (NewBuffer
!= NULL
&& OldBuffer
!= NULL
) {
883 CopyMem (NewBuffer
, OldBuffer
, MIN (OldSize
, NewSize
));
884 FreePool (OldBuffer
);
890 Reallocates a buffer of type EfiRuntimeServicesData.
892 Allocates and zeros the number bytes specified by NewSize from memory of type
893 EfiRuntimeServicesData. If OldBuffer is not NULL, then the smaller of OldSize and
894 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
895 OldBuffer is freed. A pointer to the newly allocated buffer is returned.
896 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not
897 enough memory remaining to satisfy the request, then NULL is returned.
899 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
900 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
902 @param OldSize The size, in bytes, of OldBuffer.
903 @param NewSize The size, in bytes, of the buffer to reallocate.
904 @param OldBuffer The buffer to copy to the allocated buffer. This is an optional
905 parameter that may be NULL.
907 @return A pointer to the allocated buffer or NULL if allocation fails.
915 IN VOID
*OldBuffer OPTIONAL
920 Buffer
= InternalReallocatePool (EfiRuntimeServicesData
, OldSize
, NewSize
, OldBuffer
);
921 if (Buffer
!= NULL
) {
922 MemoryProfileLibRecord (
923 (PHYSICAL_ADDRESS
) (UINTN
) RETURN_ADDRESS(0),
924 MEMORY_PROFILE_ACTION_LIB_REALLOCATE_POOL
,
925 EfiRuntimeServicesData
,
935 Reallocates a buffer of type EfiRuntimeServicesData.
937 Allocates and zeros the number bytes specified by NewSize from memory of type
938 EfiRuntimeServicesData. If OldBuffer is not NULL, then the smaller of OldSize and
939 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
940 OldBuffer is freed. A pointer to the newly allocated buffer is returned.
941 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not
942 enough memory remaining to satisfy the request, then NULL is returned.
944 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
945 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
947 @param OldSize The size, in bytes, of OldBuffer.
948 @param NewSize The size, in bytes, of the buffer to reallocate.
949 @param OldBuffer The buffer to copy to the allocated buffer. This is an optional
950 parameter that may be NULL.
952 @return A pointer to the allocated buffer or NULL if allocation fails.
957 ReallocateRuntimePool (
960 IN VOID
*OldBuffer OPTIONAL
965 Buffer
= InternalReallocatePool (EfiRuntimeServicesData
, OldSize
, NewSize
, OldBuffer
);
966 if (Buffer
!= NULL
) {
967 MemoryProfileLibRecord (
968 (PHYSICAL_ADDRESS
) (UINTN
) RETURN_ADDRESS(0),
969 MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RUNTIME_POOL
,
970 EfiRuntimeServicesData
,
980 Reallocates a buffer of type EfiReservedMemoryType.
982 Allocates and zeros the number bytes specified by NewSize from memory of type
983 EfiReservedMemoryType. If OldBuffer is not NULL, then the smaller of OldSize and
984 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
985 OldBuffer is freed. A pointer to the newly allocated buffer is returned.
986 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not
987 enough memory remaining to satisfy the request, then NULL is returned.
989 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
990 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
992 @param OldSize The size, in bytes, of OldBuffer.
993 @param NewSize The size, in bytes, of the buffer to reallocate.
994 @param OldBuffer The buffer to copy to the allocated buffer. This is an optional
995 parameter that may be NULL.
997 @return A pointer to the allocated buffer or NULL if allocation fails.
1002 ReallocateReservedPool (
1005 IN VOID
*OldBuffer OPTIONAL
1012 Frees a buffer that was previously allocated with one of the pool allocation functions in the
1013 Memory Allocation Library.
1015 Frees the buffer specified by Buffer. Buffer must have been allocated on a previous call to the
1016 pool allocation services of the Memory Allocation Library. If it is not possible to free pool
1017 resources, then this function will perform no actions.
1019 If Buffer was not allocated with a pool allocation function in the Memory Allocation Library,
1022 @param Buffer Pointer to the buffer to free.
1033 if (BufferInSmram (Buffer
)) {
1035 // When Buffer is in SMRAM range, it should be allocated by SmmAllocatePool() service.
1036 // So, SmmFreePool() service is used to free it.
1038 Status
= SmmFreePool (Buffer
);
1041 // When Buffer is out of SMRAM range, it should be allocated by gBS->AllocatePool() service.
1042 // So, gBS->FreePool() service is used to free it.
1044 Status
= gBS
->FreePool (Buffer
);
1046 ASSERT_EFI_ERROR (Status
);
1050 The constructor function calls SmmInitializeMemoryServices to initialize memory in SMRAM.
1052 @param ImageHandle The firmware allocated handle for the EFI image.
1053 @param SystemTable A pointer to the EFI System Table.
1055 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
1060 PiSmmCoreMemoryAllocationLibConstructor (
1061 IN EFI_HANDLE ImageHandle
,
1062 IN EFI_SYSTEM_TABLE
*SystemTable
1066 SMM_CORE_PRIVATE_DATA
*SmmCorePrivate
;
1068 VOID
*BootServicesData
;
1070 SmmCorePrivate
= (SMM_CORE_PRIVATE_DATA
*)ImageHandle
;
1073 // The FreePool()/FreePages() will need use SmramRanges data to know whether
1074 // the buffer to free is in SMRAM range or not. And there may be FreePool()/
1075 // FreePages() indrectly during calling SmmInitializeMemoryServices(), but
1076 // no SMRAM could be allocated before calling SmmInitializeMemoryServices(),
1077 // so temporarily use BootServicesData to hold the SmramRanges data.
1079 mSmmCoreMemoryAllocLibSmramRangeCount
= SmmCorePrivate
->SmramRangeCount
;
1080 Size
= mSmmCoreMemoryAllocLibSmramRangeCount
* sizeof (EFI_SMRAM_DESCRIPTOR
);
1081 Status
= gBS
->AllocatePool (EfiBootServicesData
, Size
, (VOID
**) &mSmmCoreMemoryAllocLibSmramRanges
);
1082 ASSERT_EFI_ERROR (Status
);
1083 ASSERT (mSmmCoreMemoryAllocLibSmramRanges
!= NULL
);
1084 CopyMem (mSmmCoreMemoryAllocLibSmramRanges
, SmmCorePrivate
->SmramRanges
, Size
);
1087 // Initialize memory service using free SMRAM
1089 SmmInitializeMemoryServices (SmmCorePrivate
->SmramRangeCount
, SmmCorePrivate
->SmramRanges
);
1092 // Move the SmramRanges data from BootServicesData to SMRAM.
1094 BootServicesData
= mSmmCoreMemoryAllocLibSmramRanges
;
1095 mSmmCoreMemoryAllocLibSmramRanges
= (EFI_SMRAM_DESCRIPTOR
*) AllocateCopyPool (Size
, (VOID
*) BootServicesData
);
1096 ASSERT (mSmmCoreMemoryAllocLibSmramRanges
!= NULL
);
1099 // Free the temporarily used BootServicesData.
1101 Status
= gBS
->FreePool (BootServicesData
);
1102 ASSERT_EFI_ERROR (Status
);