Message ID | 20190116202236.6977-3-ard.biesheuvel@linaro.org |
---|---|
State | Accepted |
Commit | 66dde0c7516b82a8a70926a72a0d8028e96405fd |
Headers | show |
Series | StandaloneMmPkg: assorted fixes and improvements | expand |
Reviewed-by: jiewen.yao@intel.com > -----Original Message----- > From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org] > Sent: Wednesday, January 16, 2019 12:22 PM > To: edk2-devel@lists.01.org > Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>; Achin Gupta > <achin.gupta@arm.com>; Yao, Jiewen <jiewen.yao@intel.com>; Supreeth > Venkatesh <supreeth.venkatesh@arm.com>; Leif Lindholm > <leif.lindholm@linaro.org>; Jagadeesh Ujja <jagadeesh.ujja@arm.com>; > Thomas Panakamattam Abraham <thomas.abraham@arm.com>; Sami > Mujawar <Sami.Mujawar@arm.com> > Subject: [PATCH v2 02/11] StandaloneMmPkg: add MM_STANDALONE > MemoryAllocationLib implementation > > This MemoryAllocationLib code is based on the staging implementation of > StandaloneMmPkg, with the following changes: > - use correct MODULE_TYPE > - include MmServicesTableLib instead of declaring gMmst directly > - update code comments referring to the MM core > > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Jagadeesh Ujja <jagadeesh.ujja@arm.com> > Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> > --- > > StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/Standalone > MmMemoryAllocationLib.c | 822 ++++++++++++++++++++ > > StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/Standalone > MmMemoryAllocationLib.inf | 42 + > 2 files changed, 864 insertions(+) > > diff --git > a/StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/Standalo > neMmMemoryAllocationLib.c > b/StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/Standalo > neMmMemoryAllocationLib.c > new file mode 100644 > index 000000000000..c7c1282babff > --- /dev/null > +++ > b/StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/Standalo > neMmMemoryAllocationLib.c > @@ -0,0 +1,822 @@ > +/** @file > + Support routines for memory allocation routines based on Standalone > MM Core internal functions. > + > + Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> > + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR> > + > + This program and the accompanying materials > + are licensed and made available under the terms and conditions of the > BSD License > + which accompanies this distribution. The full text of the license may be > found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" > BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS OR IMPLIED. > + > +**/ > + > +#include <PiMm.h> > + > +#include <Library/BaseMemoryLib.h> > +#include <Library/DebugLib.h> > +#include <Library/MemoryAllocationLib.h> > +#include <Library/MmServicesTableLib.h> > + > +/** > + Allocates one or more 4KB pages of a certain memory type. > + > + Allocates the number of 4KB pages of a certain memory type and returns > a pointer to the allocated > + buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, > then NULL is returned. > + If there is not enough memory remaining to satisfy the request, then > NULL is returned. > + > + @param MemoryType The type of memory to allocate. > + @param Pages The number of 4 KB pages to > allocate. > + > + @return A pointer to the allocated buffer or NULL if allocation fails. > + > +**/ > +VOID * > +InternalAllocatePages ( > + IN EFI_MEMORY_TYPE MemoryType, > + IN UINTN Pages > + ) > +{ > + EFI_STATUS Status; > + EFI_PHYSICAL_ADDRESS Memory; > + > + if (Pages == 0) { > + return NULL; > + } > + > + Status = gMmst->MmAllocatePages (AllocateAnyPages, MemoryType, > Pages, &Memory); > + if (EFI_ERROR (Status)) { > + return NULL; > + } > + return (VOID *)(UINTN)Memory; > +} > + > +/** > + Allocates one or more 4KB pages of type EfiBootServicesData. > + > + Allocates the number of 4KB pages of type EfiBootServicesData and > returns a pointer to the > + allocated buffer. The buffer returned is aligned on a 4KB boundary. If > Pages is 0, then NULL > + is returned. If there is not enough memory remaining to satisfy the > request, then NULL is > + returned. > + > + @param Pages The number of 4 KB pages to > allocate. > + > + @return A pointer to the allocated buffer or NULL if allocation fails. > + > +**/ > +VOID * > +EFIAPI > +AllocatePages ( > + IN UINTN Pages > + ) > +{ > + return InternalAllocatePages (EfiRuntimeServicesData, Pages); > +} > + > +/** > + Allocates one or more 4KB pages of type EfiRuntimeServicesData. > + > + Allocates the number of 4KB pages of type EfiRuntimeServicesData and > returns a pointer to the > + allocated buffer. The buffer returned is aligned on a 4KB boundary. If > Pages is 0, then NULL > + is returned. If there is not enough memory remaining to satisfy the > request, then NULL is > + returned. > + > + @param Pages The number of 4 KB pages to > allocate. > + > + @return A pointer to the allocated buffer or NULL if allocation fails. > + > +**/ > +VOID * > +EFIAPI > +AllocateRuntimePages ( > + IN UINTN Pages > + ) > +{ > + return InternalAllocatePages (EfiRuntimeServicesData, Pages); > +} > + > +/** > + Allocates one or more 4KB pages of type EfiReservedMemoryType. > + > + Allocates the number of 4KB pages of type EfiReservedMemoryType and > returns a pointer to the > + allocated buffer. The buffer returned is aligned on a 4KB boundary. If > Pages is 0, then NULL > + is returned. If there is not enough memory remaining to satisfy the > request, then NULL is > + returned. > + > + @param Pages The number of 4 KB pages to > allocate. > + > + @return A pointer to the allocated buffer or NULL if allocation fails. > + > +**/ > +VOID * > +EFIAPI > +AllocateReservedPages ( > + IN UINTN Pages > + ) > +{ > + return NULL; > +} > + > +/** > + Frees one or more 4KB pages that were previously allocated with one of > the page allocation > + functions in the Memory Allocation Library. > + > + Frees the number of 4KB pages specified by Pages from the buffer > specified by Buffer. Buffer > + must have been allocated on a previous call to the page allocation > services of the Memory > + Allocation Library. If it is not possible to free allocated pages, then this > function will > + perform no actions. > + > + If Buffer was not allocated with a page allocation function in the > Memory Allocation Library, > + then ASSERT(). > + If Pages is zero, then ASSERT(). > + > + @param Buffer Pointer to the buffer of pages to > free. > + @param Pages The number of 4 KB pages to free. > + > +**/ > +VOID > +EFIAPI > +FreePages ( > + IN VOID *Buffer, > + IN UINTN Pages > + ) > +{ > + EFI_STATUS Status; > + > + ASSERT (Pages != 0); > + Status = gMmst->MmFreePages ((EFI_PHYSICAL_ADDRESS) > (UINTN)Buffer, Pages); > + ASSERT_EFI_ERROR (Status); > +} > + > +/** > + Allocates one or more 4KB pages of a certain memory type at a specified > alignment. > + > + Allocates the number of 4KB pages specified by Pages of a certain > memory type with an alignment > + specified by Alignment. The allocated buffer is returned. If Pages is 0, > then NULL is returned. > + If there is not enough memory at the specified alignment remaining to > satisfy the request, then > + NULL is returned. > + If Alignment is not a power of two and Alignment is not zero, then > ASSERT(). > + If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). > + > + @param MemoryType The type of memory to allocate. > + @param Pages The number of 4 KB pages to > allocate. > + @param Alignment The requested alignment of the > allocation. Must be a power of two. > + If Alignment is zero, then byte > alignment is used. > + > + @return A pointer to the allocated buffer or NULL if allocation fails. > + > +**/ > +VOID * > +InternalAllocateAlignedPages ( > + IN EFI_MEMORY_TYPE MemoryType, > + IN UINTN Pages, > + IN UINTN Alignment > + ) > +{ > + EFI_STATUS Status; > + EFI_PHYSICAL_ADDRESS Memory; > + UINTN AlignedMemory; > + UINTN AlignmentMask; > + UINTN UnalignedPages; > + UINTN RealPages; > + > + // > + // Alignment must be a power of two or zero. > + // > + ASSERT ((Alignment & (Alignment - 1)) == 0); > + > + if (Pages == 0) { > + return NULL; > + } > + if (Alignment > EFI_PAGE_SIZE) { > + // > + // Calculate the total number of pages since alignment is larger than > page size. > + // > + AlignmentMask = Alignment - 1; > + RealPages = Pages + EFI_SIZE_TO_PAGES (Alignment); > + // > + // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not > overflow. > + // > + ASSERT (RealPages > Pages); > + > + Status = gMmst->MmAllocatePages (AllocateAnyPages, > MemoryType, RealPages, &Memory); > + if (EFI_ERROR (Status)) { > + return NULL; > + } > + AlignedMemory = ((UINTN)Memory + AlignmentMask) & > ~AlignmentMask; > + UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN) > Memory); > + if (UnalignedPages > 0) { > + // > + // Free first unaligned page(s). > + // > + Status = gMmst->MmFreePages (Memory, UnalignedPages); > + ASSERT_EFI_ERROR (Status); > + } > + Memory = (EFI_PHYSICAL_ADDRESS)(AlignedMemory + > EFI_PAGES_TO_SIZE (Pages)); > + UnalignedPages = RealPages - Pages - UnalignedPages; > + if (UnalignedPages > 0) { > + // > + // Free last unaligned page(s). > + // > + Status = gMmst->MmFreePages (Memory, UnalignedPages); > + ASSERT_EFI_ERROR (Status); > + } > + } else { > + // > + // Do not over-allocate pages in this case. > + // > + Status = gMmst->MmAllocatePages (AllocateAnyPages, MemoryType, > Pages, &Memory); > + if (EFI_ERROR (Status)) { > + return NULL; > + } > + AlignedMemory = (UINTN) Memory; > + } > + return (VOID *) AlignedMemory; > +} > + > +/** > + Allocates one or more 4KB pages of type EfiBootServicesData at a > specified alignment. > + > + Allocates the number of 4KB pages specified by Pages of type > EfiBootServicesData with an > + alignment specified by Alignment. The allocated buffer is returned. If > Pages is 0, then NULL is > + returned. If there is not enough memory at the specified alignment > remaining to satisfy the > + request, then NULL is returned. > + > + If Alignment is not a power of two and Alignment is not zero, then > ASSERT(). > + If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). > + > + @param Pages The number of 4 KB pages to > allocate. > + @param Alignment The requested alignment of the > allocation. Must be a power of two. > + If Alignment is zero, then byte > alignment is used. > + > + @return A pointer to the allocated buffer or NULL if allocation fails. > + > +**/ > +VOID * > +EFIAPI > +AllocateAlignedPages ( > + IN UINTN Pages, > + IN UINTN Alignment > + ) > +{ > + return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, > Alignment); > +} > + > +/** > + Allocates one or more 4KB pages of type EfiRuntimeServicesData at a > specified alignment. > + > + Allocates the number of 4KB pages specified by Pages of type > EfiRuntimeServicesData with an > + alignment specified by Alignment. The allocated buffer is returned. If > Pages is 0, then NULL is > + returned. If there is not enough memory at the specified alignment > remaining to satisfy the > + request, then NULL is returned. > + > + If Alignment is not a power of two and Alignment is not zero, then > ASSERT(). > + If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). > + > + @param Pages The number of 4 KB pages to > allocate. > + @param Alignment The requested alignment of the > allocation. Must be a power of two. > + If Alignment is zero, then byte > alignment is used. > + > + @return A pointer to the allocated buffer or NULL if allocation fails. > + > +**/ > +VOID * > +EFIAPI > +AllocateAlignedRuntimePages ( > + IN UINTN Pages, > + IN UINTN Alignment > + ) > +{ > + return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, > Alignment); > +} > + > +/** > + Allocates one or more 4KB pages of type EfiReservedMemoryType at a > specified alignment. > + > + Allocates the number of 4KB pages specified by Pages of type > EfiReservedMemoryType with an > + alignment specified by Alignment. The allocated buffer is returned. If > Pages is 0, then NULL is > + returned. If there is not enough memory at the specified alignment > remaining to satisfy the > + request, then NULL is returned. > + > + If Alignment is not a power of two and Alignment is not zero, then > ASSERT(). > + If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). > + > + @param Pages The number of 4 KB pages to > allocate. > + @param Alignment The requested alignment of the > allocation. Must be a power of two. > + If Alignment is zero, then byte > alignment is used. > + > + @return A pointer to the allocated buffer or NULL if allocation fails. > + > +**/ > +VOID * > +EFIAPI > +AllocateAlignedReservedPages ( > + IN UINTN Pages, > + IN UINTN Alignment > + ) > +{ > + return NULL; > +} > + > +/** > + Frees one or more 4KB pages that were previously allocated with one of > the aligned page > + allocation functions in the Memory Allocation Library. > + > + Frees the number of 4KB pages specified by Pages from the buffer > specified by Buffer. Buffer > + must have been allocated on a previous call to the aligned page > allocation services of the Memory > + Allocation Library. If it is not possible to free allocated pages, then this > function will > + perform no actions. > + > + If Buffer was not allocated with an aligned page allocation function in > the Memory Allocation > + Library, then ASSERT(). > + If Pages is zero, then ASSERT(). > + > + @param Buffer Pointer to the buffer of pages to > free. > + @param Pages The number of 4 KB pages to free. > + > +**/ > +VOID > +EFIAPI > +FreeAlignedPages ( > + IN VOID *Buffer, > + IN UINTN Pages > + ) > +{ > + EFI_STATUS Status; > + > + ASSERT (Pages != 0); > + Status = gMmst->MmFreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, > Pages); > + ASSERT_EFI_ERROR (Status); > +} > + > +/** > + Allocates a buffer of a certain pool type. > + > + Allocates the number bytes specified by AllocationSize of a certain pool > type and returns a > + pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer > of 0 size is > + returned. If there is not enough memory remaining to satisfy the > request, then NULL is returned. > + > + @param MemoryType The type of memory to allocate. > + @param AllocationSize The number of bytes to allocate. > + > + @return A pointer to the allocated buffer or NULL if allocation fails. > + > +**/ > +VOID * > +InternalAllocatePool ( > + IN EFI_MEMORY_TYPE MemoryType, > + IN UINTN AllocationSize > + ) > +{ > + EFI_STATUS Status; > + VOID *Memory; > + > + Memory = NULL; > + > + Status = gMmst->MmAllocatePool (MemoryType, AllocationSize, > &Memory); > + if (EFI_ERROR (Status)) { > + Memory = NULL; > + } > + return Memory; > +} > + > +/** > + Allocates a buffer of type EfiBootServicesData. > + > + Allocates the number bytes specified by AllocationSize of type > EfiBootServicesData and returns a > + pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer > of 0 size is > + returned. If there is not enough memory remaining to satisfy the > request, then NULL is returned. > + > + @param AllocationSize The number of bytes to allocate. > + > + @return A pointer to the allocated buffer or NULL if allocation fails. > + > +**/ > +VOID * > +EFIAPI > +AllocatePool ( > + IN UINTN AllocationSize > + ) > +{ > + return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize); > +} > + > +/** > + Allocates a buffer of type EfiRuntimeServicesData. > + > + Allocates the number bytes specified by AllocationSize of type > EfiRuntimeServicesData and returns > + a pointer to the allocated buffer. If AllocationSize is 0, then a valid > buffer of 0 size is > + returned. If there is not enough memory remaining to satisfy the > request, then NULL is returned. > + > + @param AllocationSize The number of bytes to allocate. > + > + @return A pointer to the allocated buffer or NULL if allocation fails. > + > +**/ > +VOID * > +EFIAPI > +AllocateRuntimePool ( > + IN UINTN AllocationSize > + ) > +{ > + return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize); > +} > + > +/** > + Allocates a buffer of type EfiReservedMemoryType. > + > + Allocates the number bytes specified by AllocationSize of type > EfiReservedMemoryType and returns > + a pointer to the allocated buffer. If AllocationSize is 0, then a valid > buffer of 0 size is > + returned. If there is not enough memory remaining to satisfy the > request, then NULL is returned. > + > + @param AllocationSize The number of bytes to allocate. > + > + @return A pointer to the allocated buffer or NULL if allocation fails. > + > +**/ > +VOID * > +EFIAPI > +AllocateReservedPool ( > + IN UINTN AllocationSize > + ) > +{ > + return NULL; > +} > + > +/** > + Allocates and zeros a buffer of a certain pool type. > + > + Allocates the number bytes specified by AllocationSize of a certain pool > type, clears the buffer > + with zeros, and returns a pointer to the allocated buffer. If > AllocationSize is 0, then a valid > + buffer of 0 size is returned. If there is not enough memory remaining to > satisfy the request, > + then NULL is returned. > + > + @param PoolType The type of memory to allocate. > + @param AllocationSize The number of bytes to allocate and > zero. > + > + @return A pointer to the allocated buffer or NULL if allocation fails. > + > +**/ > +VOID * > +InternalAllocateZeroPool ( > + IN EFI_MEMORY_TYPE PoolType, > + IN UINTN AllocationSize > + ) > +{ > + VOID *Memory; > + > + Memory = InternalAllocatePool (PoolType, AllocationSize); > + if (Memory != NULL) { > + Memory = ZeroMem (Memory, AllocationSize); > + } > + return Memory; > +} > + > +/** > + Allocates and zeros a buffer of type EfiBootServicesData. > + > + Allocates the number bytes specified by AllocationSize of type > EfiBootServicesData, clears the > + buffer with zeros, and returns a pointer to the allocated buffer. If > AllocationSize is 0, then a > + valid buffer of 0 size is returned. If there is not enough memory > remaining to satisfy the > + request, then NULL is returned. > + > + @param AllocationSize The number of bytes to allocate and > zero. > + > + @return A pointer to the allocated buffer or NULL if allocation fails. > + > +**/ > +VOID * > +EFIAPI > +AllocateZeroPool ( > + IN UINTN AllocationSize > + ) > +{ > + return InternalAllocateZeroPool (EfiRuntimeServicesData, > AllocationSize); > +} > + > +/** > + Allocates and zeros a buffer of type EfiRuntimeServicesData. > + > + Allocates the number bytes specified by AllocationSize of type > EfiRuntimeServicesData, clears the > + buffer with zeros, and returns a pointer to the allocated buffer. If > AllocationSize is 0, then a > + valid buffer of 0 size is returned. If there is not enough memory > remaining to satisfy the > + request, then NULL is returned. > + > + @param AllocationSize The number of bytes to allocate and > zero. > + > + @return A pointer to the allocated buffer or NULL if allocation fails. > + > +**/ > +VOID * > +EFIAPI > +AllocateRuntimeZeroPool ( > + IN UINTN AllocationSize > + ) > +{ > + return InternalAllocateZeroPool (EfiRuntimeServicesData, > AllocationSize); > +} > + > +/** > + Allocates and zeros a buffer of type EfiReservedMemoryType. > + > + Allocates the number bytes specified by AllocationSize of type > EfiReservedMemoryType, clears the > + buffer with zeros, and returns a pointer to the allocated buffer. If > AllocationSize is 0, then a > + valid buffer of 0 size is returned. If there is not enough memory > remaining to satisfy the > + request, then NULL is returned. > + > + @param AllocationSize The number of bytes to allocate and > zero. > + > + @return A pointer to the allocated buffer or NULL if allocation fails. > + > +**/ > +VOID * > +EFIAPI > +AllocateReservedZeroPool ( > + IN UINTN AllocationSize > + ) > +{ > + return NULL; > +} > + > +/** > + Copies a buffer to an allocated buffer of a certain pool type. > + > + Allocates the number bytes specified by AllocationSize of a certain pool > type, copies > + AllocationSize bytes from Buffer to the newly allocated buffer, and > returns a pointer to the > + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is > returned. If there > + is not enough memory remaining to satisfy the request, then NULL is > returned. > + If Buffer is NULL, then ASSERT(). > + If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then > ASSERT(). > + > + @param PoolType The type of pool to allocate. > + @param AllocationSize The number of bytes to allocate and > zero. > + @param Buffer The buffer to copy to the allocated > buffer. > + > + @return A pointer to the allocated buffer or NULL if allocation fails. > + > +**/ > +VOID * > +InternalAllocateCopyPool ( > + IN EFI_MEMORY_TYPE PoolType, > + IN UINTN AllocationSize, > + IN CONST VOID *Buffer > + ) > +{ > + VOID *Memory; > + > + ASSERT (Buffer != NULL); > + ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1)); > + > + Memory = InternalAllocatePool (PoolType, AllocationSize); > + if (Memory != NULL) { > + Memory = CopyMem (Memory, Buffer, AllocationSize); > + } > + return Memory; > +} > + > +/** > + Copies a buffer to an allocated buffer of type EfiBootServicesData. > + > + Allocates the number bytes specified by AllocationSize of type > EfiBootServicesData, copies > + AllocationSize bytes from Buffer to the newly allocated buffer, and > returns a pointer to the > + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is > returned. If there > + is not enough memory remaining to satisfy the request, then NULL is > returned. > + > + If Buffer is NULL, then ASSERT(). > + If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then > ASSERT(). > + > + @param AllocationSize The number of bytes to allocate and > zero. > + @param Buffer The buffer to copy to the allocated > buffer. > + > + @return A pointer to the allocated buffer or NULL if allocation fails. > + > +**/ > +VOID * > +EFIAPI > +AllocateCopyPool ( > + IN UINTN AllocationSize, > + IN CONST VOID *Buffer > + ) > +{ > + return InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, > Buffer); > +} > + > +/** > + Copies a buffer to an allocated buffer of type EfiRuntimeServicesData. > + > + Allocates the number bytes specified by AllocationSize of type > EfiRuntimeServicesData, copies > + AllocationSize bytes from Buffer to the newly allocated buffer, and > returns a pointer to the > + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is > returned. If there > + is not enough memory remaining to satisfy the request, then NULL is > returned. > + > + If Buffer is NULL, then ASSERT(). > + If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then > ASSERT(). > + > + @param AllocationSize The number of bytes to allocate and > zero. > + @param Buffer The buffer to copy to the allocated > buffer. > + > + @return A pointer to the allocated buffer or NULL if allocation fails. > + > +**/ > +VOID * > +EFIAPI > +AllocateRuntimeCopyPool ( > + IN UINTN AllocationSize, > + IN CONST VOID *Buffer > + ) > +{ > + return InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, > Buffer); > +} > + > +/** > + Copies a buffer to an allocated buffer of type EfiReservedMemoryType. > + > + Allocates the number bytes specified by AllocationSize of type > EfiReservedMemoryType, copies > + AllocationSize bytes from Buffer to the newly allocated buffer, and > returns a pointer to the > + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is > returned. If there > + is not enough memory remaining to satisfy the request, then NULL is > returned. > + > + If Buffer is NULL, then ASSERT(). > + If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then > ASSERT(). > + > + @param AllocationSize The number of bytes to allocate and > zero. > + @param Buffer The buffer to copy to the allocated > buffer. > + > + @return A pointer to the allocated buffer or NULL if allocation fails. > + > +**/ > +VOID * > +EFIAPI > +AllocateReservedCopyPool ( > + IN UINTN AllocationSize, > + IN CONST VOID *Buffer > + ) > +{ > + return NULL; > +} > + > +/** > + Reallocates a buffer of a specified memory type. > + > + Allocates and zeros the number bytes specified by NewSize from memory > of the type > + specified by PoolType. If OldBuffer is not NULL, then the smaller of > OldSize and > + NewSize bytes are copied from OldBuffer to the newly allocated buffer, > and > + OldBuffer is freed. A pointer to the newly allocated buffer is returned. > + If NewSize is 0, then a valid buffer of 0 size is returned. If there is not > + enough memory remaining to satisfy the request, then NULL is returned. > + > + If the allocation of the new buffer is successful and the smaller of > NewSize and OldSize > + is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). > + > + @param PoolType The type of pool to allocate. > + @param OldSize The size, in bytes, of OldBuffer. > + @param NewSize The size, in bytes, of the buffer to > reallocate. > + @param OldBuffer The buffer to copy to the allocated buffer. > This is an optional > + parameter that may be NULL. > + > + @return A pointer to the allocated buffer or NULL if allocation fails. > + > +**/ > +VOID * > +InternalReallocatePool ( > + IN EFI_MEMORY_TYPE PoolType, > + IN UINTN OldSize, > + IN UINTN NewSize, > + IN VOID *OldBuffer OPTIONAL > + ) > +{ > + VOID *NewBuffer; > + > + NewBuffer = InternalAllocateZeroPool (PoolType, NewSize); > + if (NewBuffer != NULL && OldBuffer != NULL) { > + CopyMem (NewBuffer, OldBuffer, MIN (OldSize, NewSize)); > + FreePool (OldBuffer); > + } > + return NewBuffer; > +} > + > +/** > + Reallocates a buffer of type EfiBootServicesData. > + > + Allocates and zeros the number bytes specified by NewSize from memory > of type > + EfiBootServicesData. If OldBuffer is not NULL, then the smaller of > OldSize and > + NewSize bytes are copied from OldBuffer to the newly allocated buffer, > and > + OldBuffer is freed. A pointer to the newly allocated buffer is returned. > + If NewSize is 0, then a valid buffer of 0 size is returned. If there is not > + enough memory remaining to satisfy the request, then NULL is returned. > + > + If the allocation of the new buffer is successful and the smaller of > NewSize and OldSize > + is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). > + > + @param OldSize The size, in bytes, of OldBuffer. > + @param NewSize The size, in bytes, of the buffer to > reallocate. > + @param OldBuffer The buffer to copy to the allocated buffer. > This is an optional > + parameter that may be NULL. > + > + @return A pointer to the allocated buffer or NULL if allocation fails. > + > +**/ > +VOID * > +EFIAPI > +ReallocatePool ( > + IN UINTN OldSize, > + IN UINTN NewSize, > + IN VOID *OldBuffer OPTIONAL > + ) > +{ > + return InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, > OldBuffer); > +} > + > +/** > + Reallocates a buffer of type EfiRuntimeServicesData. > + > + Allocates and zeros the number bytes specified by NewSize from memory > of type > + EfiRuntimeServicesData. If OldBuffer is not NULL, then the smaller of > OldSize and > + NewSize bytes are copied from OldBuffer to the newly allocated buffer, > and > + OldBuffer is freed. A pointer to the newly allocated buffer is returned. > + If NewSize is 0, then a valid buffer of 0 size is returned. If there is not > + enough memory remaining to satisfy the request, then NULL is returned. > + > + If the allocation of the new buffer is successful and the smaller of > NewSize and OldSize > + is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). > + > + @param OldSize The size, in bytes, of OldBuffer. > + @param NewSize The size, in bytes, of the buffer to > reallocate. > + @param OldBuffer The buffer to copy to the allocated buffer. > This is an optional > + parameter that may be NULL. > + > + @return A pointer to the allocated buffer or NULL if allocation fails. > + > +**/ > +VOID * > +EFIAPI > +ReallocateRuntimePool ( > + IN UINTN OldSize, > + IN UINTN NewSize, > + IN VOID *OldBuffer OPTIONAL > + ) > +{ > + return InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, > OldBuffer); > +} > + > +/** > + Reallocates a buffer of type EfiReservedMemoryType. > + > + Allocates and zeros the number bytes specified by NewSize from memory > of type > + EfiReservedMemoryType. If OldBuffer is not NULL, then the smaller of > OldSize and > + NewSize bytes are copied from OldBuffer to the newly allocated buffer, > and > + OldBuffer is freed. A pointer to the newly allocated buffer is returned. > + If NewSize is 0, then a valid buffer of 0 size is returned. If there is not > + enough memory remaining to satisfy the request, then NULL is returned. > + > + If the allocation of the new buffer is successful and the smaller of > NewSize and OldSize > + is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). > + > + @param OldSize The size, in bytes, of OldBuffer. > + @param NewSize The size, in bytes, of the buffer to > reallocate. > + @param OldBuffer The buffer to copy to the allocated buffer. > This is an optional > + parameter that may be NULL. > + > + @return A pointer to the allocated buffer or NULL if allocation fails. > + > +**/ > +VOID * > +EFIAPI > +ReallocateReservedPool ( > + IN UINTN OldSize, > + IN UINTN NewSize, > + IN VOID *OldBuffer OPTIONAL > + ) > +{ > + return NULL; > +} > + > +/** > + Frees a buffer that was previously allocated with one of the pool > allocation functions in the > + Memory Allocation Library. > + > + Frees the buffer specified by Buffer. Buffer must have been allocated > on a previous call to the > + pool allocation services of the Memory Allocation Library. If it is not > possible to free pool > + resources, then this function will perform no actions. > + > + If Buffer was not allocated with a pool allocation function in the Memory > Allocation Library, > + then ASSERT(). > + > + @param Buffer Pointer to the buffer to free. > + > +**/ > +VOID > +EFIAPI > +FreePool ( > + IN VOID *Buffer > + ) > +{ > + EFI_STATUS Status; > + > + Status = gMmst->MmFreePool (Buffer); > + ASSERT_EFI_ERROR (Status); > +} > + > diff --git > a/StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/Standalo > neMmMemoryAllocationLib.inf > b/StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/Standalo > neMmMemoryAllocationLib.inf > new file mode 100644 > index 000000000000..8776e34e7c06 > --- /dev/null > +++ > b/StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/Standalo > neMmMemoryAllocationLib.inf > @@ -0,0 +1,42 @@ > +## @file > +# Memory Allocation Library instance standalone MM modules. > +# > +# Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR> > +# Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR> > +# Copyright (c) 2018, Linaro, Ltd. All rights reserved.<BR> > +# > +# This program and the accompanying materials > +# are licensed and made available under the terms and conditions of the > BSD License > +# which accompanies this distribution. The full text of the license may be > found at > +# http://opensource.org/licenses/bsd-license.php > +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS > IS" BASIS, > +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS OR IMPLIED. > +# > +## > + > +[Defines] > + INF_VERSION = 0x0001001B > + BASE_NAME = MemoryAllocationLib > + FILE_GUID = > 54646378-A9DC-473F-9BE1-BD027C4C76DE > + MODULE_TYPE = MM_STANDALONE > + VERSION_STRING = 1.0 > + PI_SPECIFICATION_VERSION = 0x00010032 > + LIBRARY_CLASS = > MemoryAllocationLib|MM_STANDALONE > + > +# > +# The following information is for reference only and not required by the > build tools. > +# > +# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 > +# > + > +[Sources] > + StandaloneMmMemoryAllocationLib.c > + > +[Packages] > + MdePkg/MdePkg.dec > + StandaloneMmPkg/StandaloneMmPkg.dec > + > +[LibraryClasses] > + BaseMemoryLib > + DebugLib > + MmServicesTableLib > -- > 2.17.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
diff --git a/StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/StandaloneMmMemoryAllocationLib.c b/StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/StandaloneMmMemoryAllocationLib.c new file mode 100644 index 000000000000..c7c1282babff --- /dev/null +++ b/StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/StandaloneMmMemoryAllocationLib.c @@ -0,0 +1,822 @@ +/** @file + Support routines for memory allocation routines based on Standalone MM Core internal functions. + + Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> + Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR> + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include <PiMm.h> + +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/MmServicesTableLib.h> + +/** + Allocates one or more 4KB pages of a certain memory type. + + Allocates the number of 4KB pages of a certain memory type and returns a pointer to the allocated + buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + + @param MemoryType The type of memory to allocate. + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalAllocatePages ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS Memory; + + if (Pages == 0) { + return NULL; + } + + Status = gMmst->MmAllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory); + if (EFI_ERROR (Status)) { + return NULL; + } + return (VOID *)(UINTN)Memory; +} + +/** + Allocates one or more 4KB pages of type EfiBootServicesData. + + Allocates the number of 4KB pages of type EfiBootServicesData and returns a pointer to the + allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL + is returned. If there is not enough memory remaining to satisfy the request, then NULL is + returned. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocatePages ( + IN UINTN Pages + ) +{ + return InternalAllocatePages (EfiRuntimeServicesData, Pages); +} + +/** + Allocates one or more 4KB pages of type EfiRuntimeServicesData. + + Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the + allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL + is returned. If there is not enough memory remaining to satisfy the request, then NULL is + returned. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateRuntimePages ( + IN UINTN Pages + ) +{ + return InternalAllocatePages (EfiRuntimeServicesData, Pages); +} + +/** + Allocates one or more 4KB pages of type EfiReservedMemoryType. + + Allocates the number of 4KB pages of type EfiReservedMemoryType and returns a pointer to the + allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL + is returned. If there is not enough memory remaining to satisfy the request, then NULL is + returned. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateReservedPages ( + IN UINTN Pages + ) +{ + return NULL; +} + +/** + Frees one or more 4KB pages that were previously allocated with one of the page allocation + functions in the Memory Allocation Library. + + Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer + must have been allocated on a previous call to the page allocation services of the Memory + Allocation Library. If it is not possible to free allocated pages, then this function will + perform no actions. + + If Buffer was not allocated with a page allocation function in the Memory Allocation Library, + then ASSERT(). + If Pages is zero, then ASSERT(). + + @param Buffer Pointer to the buffer of pages to free. + @param Pages The number of 4 KB pages to free. + +**/ +VOID +EFIAPI +FreePages ( + IN VOID *Buffer, + IN UINTN Pages + ) +{ + EFI_STATUS Status; + + ASSERT (Pages != 0); + Status = gMmst->MmFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN)Buffer, Pages); + ASSERT_EFI_ERROR (Status); +} + +/** + Allocates one or more 4KB pages of a certain memory type at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of a certain memory type with an alignment + specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is returned. + If there is not enough memory at the specified alignment remaining to satisfy the request, then + NULL is returned. + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). + + @param MemoryType The type of memory to allocate. + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalAllocateAlignedPages ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN UINTN Alignment + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS Memory; + UINTN AlignedMemory; + UINTN AlignmentMask; + UINTN UnalignedPages; + UINTN RealPages; + + // + // Alignment must be a power of two or zero. + // + ASSERT ((Alignment & (Alignment - 1)) == 0); + + if (Pages == 0) { + return NULL; + } + if (Alignment > EFI_PAGE_SIZE) { + // + // Calculate the total number of pages since alignment is larger than page size. + // + AlignmentMask = Alignment - 1; + RealPages = Pages + EFI_SIZE_TO_PAGES (Alignment); + // + // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow. + // + ASSERT (RealPages > Pages); + + Status = gMmst->MmAllocatePages (AllocateAnyPages, MemoryType, RealPages, &Memory); + if (EFI_ERROR (Status)) { + return NULL; + } + AlignedMemory = ((UINTN)Memory + AlignmentMask) & ~AlignmentMask; + UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN) Memory); + if (UnalignedPages > 0) { + // + // Free first unaligned page(s). + // + Status = gMmst->MmFreePages (Memory, UnalignedPages); + ASSERT_EFI_ERROR (Status); + } + Memory = (EFI_PHYSICAL_ADDRESS)(AlignedMemory + EFI_PAGES_TO_SIZE (Pages)); + UnalignedPages = RealPages - Pages - UnalignedPages; + if (UnalignedPages > 0) { + // + // Free last unaligned page(s). + // + Status = gMmst->MmFreePages (Memory, UnalignedPages); + ASSERT_EFI_ERROR (Status); + } + } else { + // + // Do not over-allocate pages in this case. + // + Status = gMmst->MmAllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory); + if (EFI_ERROR (Status)) { + return NULL; + } + AlignedMemory = (UINTN) Memory; + } + return (VOID *) AlignedMemory; +} + +/** + Allocates one or more 4KB pages of type EfiBootServicesData at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData with an + alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is + returned. If there is not enough memory at the specified alignment remaining to satisfy the + request, then NULL is returned. + + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateAlignedPages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment); +} + +/** + Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData with an + alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is + returned. If there is not enough memory at the specified alignment remaining to satisfy the + request, then NULL is returned. + + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateAlignedRuntimePages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment); +} + +/** + Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType with an + alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is + returned. If there is not enough memory at the specified alignment remaining to satisfy the + request, then NULL is returned. + + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT(). + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateAlignedReservedPages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + return NULL; +} + +/** + Frees one or more 4KB pages that were previously allocated with one of the aligned page + allocation functions in the Memory Allocation Library. + + Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer + must have been allocated on a previous call to the aligned page allocation services of the Memory + Allocation Library. If it is not possible to free allocated pages, then this function will + perform no actions. + + If Buffer was not allocated with an aligned page allocation function in the Memory Allocation + Library, then ASSERT(). + If Pages is zero, then ASSERT(). + + @param Buffer Pointer to the buffer of pages to free. + @param Pages The number of 4 KB pages to free. + +**/ +VOID +EFIAPI +FreeAlignedPages ( + IN VOID *Buffer, + IN UINTN Pages + ) +{ + EFI_STATUS Status; + + ASSERT (Pages != 0); + Status = gMmst->MmFreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, Pages); + ASSERT_EFI_ERROR (Status); +} + +/** + Allocates a buffer of a certain pool type. + + Allocates the number bytes specified by AllocationSize of a certain pool type and returns a + pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is + returned. If there is not enough memory remaining to satisfy the request, then NULL is returned. + + @param MemoryType The type of memory to allocate. + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalAllocatePool ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN AllocationSize + ) +{ + EFI_STATUS Status; + VOID *Memory; + + Memory = NULL; + + Status = gMmst->MmAllocatePool (MemoryType, AllocationSize, &Memory); + if (EFI_ERROR (Status)) { + Memory = NULL; + } + return Memory; +} + +/** + Allocates a buffer of type EfiBootServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a + pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is + returned. If there is not enough memory remaining to satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocatePool ( + IN UINTN AllocationSize + ) +{ + return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize); +} + +/** + Allocates a buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData and returns + a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is + returned. If there is not enough memory remaining to satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateRuntimePool ( + IN UINTN AllocationSize + ) +{ + return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize); +} + +/** + Allocates a buffer of type EfiReservedMemoryType. + + Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType and returns + a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is + returned. If there is not enough memory remaining to satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateReservedPool ( + IN UINTN AllocationSize + ) +{ + return NULL; +} + +/** + Allocates and zeros a buffer of a certain pool type. + + Allocates the number bytes specified by AllocationSize of a certain pool type, clears the buffer + with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a valid + buffer of 0 size is returned. If there is not enough memory remaining to satisfy the request, + then NULL is returned. + + @param PoolType The type of memory to allocate. + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalAllocateZeroPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize + ) +{ + VOID *Memory; + + Memory = InternalAllocatePool (PoolType, AllocationSize); + if (Memory != NULL) { + Memory = ZeroMem (Memory, AllocationSize); + } + return Memory; +} + +/** + Allocates and zeros a buffer of type EfiBootServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the + buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a + valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the + request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateZeroPool ( + IN UINTN AllocationSize + ) +{ + return InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize); +} + +/** + Allocates and zeros a buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, clears the + buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a + valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the + request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateRuntimeZeroPool ( + IN UINTN AllocationSize + ) +{ + return InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize); +} + +/** + Allocates and zeros a buffer of type EfiReservedMemoryType. + + Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, clears the + buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a + valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the + request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateReservedZeroPool ( + IN UINTN AllocationSize + ) +{ + return NULL; +} + +/** + Copies a buffer to an allocated buffer of a certain pool type. + + Allocates the number bytes specified by AllocationSize of a certain pool type, copies + AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there + is not enough memory remaining to satisfy the request, then NULL is returned. + If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param PoolType The type of pool to allocate. + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalAllocateCopyPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + VOID *Memory; + + ASSERT (Buffer != NULL); + ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1)); + + Memory = InternalAllocatePool (PoolType, AllocationSize); + if (Memory != NULL) { + Memory = CopyMem (Memory, Buffer, AllocationSize); + } + return Memory; +} + +/** + Copies a buffer to an allocated buffer of type EfiBootServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, copies + AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there + is not enough memory remaining to satisfy the request, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + return InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer); +} + +/** + Copies a buffer to an allocated buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, copies + AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there + is not enough memory remaining to satisfy the request, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateRuntimeCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + return InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer); +} + +/** + Copies a buffer to an allocated buffer of type EfiReservedMemoryType. + + Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, copies + AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there + is not enough memory remaining to satisfy the request, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateReservedCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + return NULL; +} + +/** + Reallocates a buffer of a specified memory type. + + Allocates and zeros the number bytes specified by NewSize from memory of the type + specified by PoolType. If OldBuffer is not NULL, then the smaller of OldSize and + NewSize bytes are copied from OldBuffer to the newly allocated buffer, and + OldBuffer is freed. A pointer to the newly allocated buffer is returned. + If NewSize is 0, then a valid buffer of 0 size is returned. If there is not + enough memory remaining to satisfy the request, then NULL is returned. + + If the allocation of the new buffer is successful and the smaller of NewSize and OldSize + is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). + + @param PoolType The type of pool to allocate. + @param OldSize The size, in bytes, of OldBuffer. + @param NewSize The size, in bytes, of the buffer to reallocate. + @param OldBuffer The buffer to copy to the allocated buffer. This is an optional + parameter that may be NULL. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +InternalReallocatePool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID *OldBuffer OPTIONAL + ) +{ + VOID *NewBuffer; + + NewBuffer = InternalAllocateZeroPool (PoolType, NewSize); + if (NewBuffer != NULL && OldBuffer != NULL) { + CopyMem (NewBuffer, OldBuffer, MIN (OldSize, NewSize)); + FreePool (OldBuffer); + } + return NewBuffer; +} + +/** + Reallocates a buffer of type EfiBootServicesData. + + Allocates and zeros the number bytes specified by NewSize from memory of type + EfiBootServicesData. If OldBuffer is not NULL, then the smaller of OldSize and + NewSize bytes are copied from OldBuffer to the newly allocated buffer, and + OldBuffer is freed. A pointer to the newly allocated buffer is returned. + If NewSize is 0, then a valid buffer of 0 size is returned. If there is not + enough memory remaining to satisfy the request, then NULL is returned. + + If the allocation of the new buffer is successful and the smaller of NewSize and OldSize + is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). + + @param OldSize The size, in bytes, of OldBuffer. + @param NewSize The size, in bytes, of the buffer to reallocate. + @param OldBuffer The buffer to copy to the allocated buffer. This is an optional + parameter that may be NULL. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +ReallocatePool ( + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID *OldBuffer OPTIONAL + ) +{ + return InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer); +} + +/** + Reallocates a buffer of type EfiRuntimeServicesData. + + Allocates and zeros the number bytes specified by NewSize from memory of type + EfiRuntimeServicesData. If OldBuffer is not NULL, then the smaller of OldSize and + NewSize bytes are copied from OldBuffer to the newly allocated buffer, and + OldBuffer is freed. A pointer to the newly allocated buffer is returned. + If NewSize is 0, then a valid buffer of 0 size is returned. If there is not + enough memory remaining to satisfy the request, then NULL is returned. + + If the allocation of the new buffer is successful and the smaller of NewSize and OldSize + is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). + + @param OldSize The size, in bytes, of OldBuffer. + @param NewSize The size, in bytes, of the buffer to reallocate. + @param OldBuffer The buffer to copy to the allocated buffer. This is an optional + parameter that may be NULL. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +ReallocateRuntimePool ( + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID *OldBuffer OPTIONAL + ) +{ + return InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer); +} + +/** + Reallocates a buffer of type EfiReservedMemoryType. + + Allocates and zeros the number bytes specified by NewSize from memory of type + EfiReservedMemoryType. If OldBuffer is not NULL, then the smaller of OldSize and + NewSize bytes are copied from OldBuffer to the newly allocated buffer, and + OldBuffer is freed. A pointer to the newly allocated buffer is returned. + If NewSize is 0, then a valid buffer of 0 size is returned. If there is not + enough memory remaining to satisfy the request, then NULL is returned. + + If the allocation of the new buffer is successful and the smaller of NewSize and OldSize + is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT(). + + @param OldSize The size, in bytes, of OldBuffer. + @param NewSize The size, in bytes, of the buffer to reallocate. + @param OldBuffer The buffer to copy to the allocated buffer. This is an optional + parameter that may be NULL. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +ReallocateReservedPool ( + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID *OldBuffer OPTIONAL + ) +{ + return NULL; +} + +/** + Frees a buffer that was previously allocated with one of the pool allocation functions in the + Memory Allocation Library. + + Frees the buffer specified by Buffer. Buffer must have been allocated on a previous call to the + pool allocation services of the Memory Allocation Library. If it is not possible to free pool + resources, then this function will perform no actions. + + If Buffer was not allocated with a pool allocation function in the Memory Allocation Library, + then ASSERT(). + + @param Buffer Pointer to the buffer to free. + +**/ +VOID +EFIAPI +FreePool ( + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + + Status = gMmst->MmFreePool (Buffer); + ASSERT_EFI_ERROR (Status); +} + diff --git a/StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/StandaloneMmMemoryAllocationLib.inf b/StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/StandaloneMmMemoryAllocationLib.inf new file mode 100644 index 000000000000..8776e34e7c06 --- /dev/null +++ b/StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/StandaloneMmMemoryAllocationLib.inf @@ -0,0 +1,42 @@ +## @file +# Memory Allocation Library instance standalone MM modules. +# +# Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR> +# Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR> +# Copyright (c) 2018, Linaro, Ltd. All rights reserved.<BR> +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x0001001B + BASE_NAME = MemoryAllocationLib + FILE_GUID = 54646378-A9DC-473F-9BE1-BD027C4C76DE + MODULE_TYPE = MM_STANDALONE + VERSION_STRING = 1.0 + PI_SPECIFICATION_VERSION = 0x00010032 + LIBRARY_CLASS = MemoryAllocationLib|MM_STANDALONE + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 +# + +[Sources] + StandaloneMmMemoryAllocationLib.c + +[Packages] + MdePkg/MdePkg.dec + StandaloneMmPkg/StandaloneMmPkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + MmServicesTableLib