mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-25 22:54:51 +02:00
MdePkg PeiMemoryAllocationLib: Update InternalAllocateAlignedPages
Update InternalAllocateAlignedPages to use PeiServicesFreePages. Let the InternalAllocateAlignedPages in PeiMemoryAllocationLib use same algorithm with InternalAllocateAlignedPages in UefiMemoryAllocationLib. Cc: Liming Gao <liming.gao@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Star Zeng <star.zeng@intel.com> Reviewed-by: Liming Gao <liming.gao@intel.com>
This commit is contained in:
parent
2132ef05c4
commit
c2ab95806b
@ -181,15 +181,12 @@ InternalAllocateAlignedPages (
|
|||||||
IN UINTN Alignment
|
IN UINTN Alignment
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
EFI_PHYSICAL_ADDRESS Memory;
|
EFI_PHYSICAL_ADDRESS Memory;
|
||||||
EFI_PHYSICAL_ADDRESS AlignedMemory;
|
UINTN AlignedMemory;
|
||||||
EFI_PEI_HOB_POINTERS Hob;
|
UINTN AlignmentMask;
|
||||||
BOOLEAN SkipBeforeMemHob;
|
UINTN UnalignedPages;
|
||||||
BOOLEAN SkipAfterMemHob;
|
UINTN RealPages;
|
||||||
EFI_PHYSICAL_ADDRESS HobBaseAddress;
|
|
||||||
UINT64 HobLength;
|
|
||||||
EFI_MEMORY_TYPE HobMemoryType;
|
|
||||||
UINTN TotalPages;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Alignment must be a power of two or zero.
|
// Alignment must be a power of two or zero.
|
||||||
@ -199,139 +196,50 @@ InternalAllocateAlignedPages (
|
|||||||
if (Pages == 0) {
|
if (Pages == 0) {
|
||||||
return NULL;
|
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.
|
// Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
|
||||||
//
|
//
|
||||||
ASSERT (Pages <= (MAX_ADDRESS - EFI_SIZE_TO_PAGES (Alignment)));
|
ASSERT (RealPages > Pages);
|
||||||
|
|
||||||
//
|
Status = PeiServicesAllocatePages (MemoryType, RealPages, &Memory);
|
||||||
// We would rather waste some memory to save PEI code size.
|
if (EFI_ERROR (Status)) {
|
||||||
// meaning in addition to the requested size for the aligned mem,
|
|
||||||
// we simply reserve an overhead memory equal to Alignmemt(page-aligned), no matter what.
|
|
||||||
// The overhead mem size could be reduced later with more involved malloc mechanisms
|
|
||||||
// (e.g., somthing that can detect the alignment boundary before allocating memory or
|
|
||||||
// can request that memory be allocated at a certain address that is aleady aligned).
|
|
||||||
//
|
|
||||||
TotalPages = Pages + (Alignment <= EFI_PAGE_SIZE ? 0 : EFI_SIZE_TO_PAGES(Alignment));
|
|
||||||
Memory = (EFI_PHYSICAL_ADDRESS) (UINTN) InternalAllocatePages (MemoryType, TotalPages);
|
|
||||||
if (Memory == 0) {
|
|
||||||
DEBUG((DEBUG_INFO, "Out of memory resource! \n"));
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
DEBUG ((DEBUG_INFO, "Allocated Memory unaligned: Address = 0x%LX, Pages = 0x%X, Type = %d \n", Memory, TotalPages, (UINTN) MemoryType));
|
AlignedMemory = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask;
|
||||||
|
UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN) Memory);
|
||||||
|
if (UnalignedPages > 0) {
|
||||||
//
|
//
|
||||||
// Alignment calculation
|
// Free first unaligned page(s).
|
||||||
//
|
//
|
||||||
AlignedMemory = Memory;
|
Status = PeiServicesFreePages (Memory, UnalignedPages);
|
||||||
if (Alignment > EFI_PAGE_SIZE) {
|
ASSERT_EFI_ERROR (Status);
|
||||||
AlignedMemory = ALIGN_VALUE (Memory, Alignment);
|
|
||||||
}
|
}
|
||||||
DEBUG ((DEBUG_INFO, "After aligning to 0x%X bytes: Address = 0x%LX, Pages = 0x%X \n", Alignment, AlignedMemory, Pages));
|
Memory = AlignedMemory + EFI_PAGES_TO_SIZE (Pages);
|
||||||
|
UnalignedPages = RealPages - Pages - UnalignedPages;
|
||||||
|
if (UnalignedPages > 0) {
|
||||||
//
|
//
|
||||||
// In general three HOBs cover the total allocated space.
|
// Free last unaligned page(s).
|
||||||
// The aligned portion is covered by the aligned mem HOB and
|
|
||||||
// the unaligned(to be freed) portions before and after the aligned portion are covered by newly created HOBs.
|
|
||||||
//
|
//
|
||||||
// Before mem HOB covers the region between "Memory" and "AlignedMemory"
|
Status = PeiServicesFreePages (Memory, UnalignedPages);
|
||||||
// Aligned mem HOB covers the region between "AlignedMemory" and "AlignedMemory + EFI_PAGES_TO_SIZE(Pages)"
|
ASSERT_EFI_ERROR (Status);
|
||||||
// After mem HOB covers the region between "AlignedMemory + EFI_PAGES_TO_SIZE(Pages)" and "Memory + EFI_PAGES_TO_SIZE(TotalPages)"
|
|
||||||
//
|
|
||||||
// The before or after mem HOBs need to be skipped under special cases where the aligned portion
|
|
||||||
// touches either the top or bottom of the original allocated space.
|
|
||||||
//
|
|
||||||
SkipBeforeMemHob = FALSE;
|
|
||||||
SkipAfterMemHob = FALSE;
|
|
||||||
if (Memory == AlignedMemory) {
|
|
||||||
SkipBeforeMemHob = TRUE;
|
|
||||||
}
|
}
|
||||||
if ((Memory + EFI_PAGES_TO_SIZE(TotalPages)) == (AlignedMemory + EFI_PAGES_TO_SIZE(Pages))) {
|
|
||||||
//
|
|
||||||
// This condition is never met in the current implementation.
|
|
||||||
// There is always some after-mem since the overhead mem(used in TotalPages)
|
|
||||||
// is no less than Alignment.
|
|
||||||
//
|
|
||||||
SkipAfterMemHob = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Search for the mem HOB referring to the original(unaligned) allocation
|
|
||||||
// and update the size and type if needed.
|
|
||||||
//
|
|
||||||
Hob.Raw = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION);
|
|
||||||
while (Hob.Raw != NULL) {
|
|
||||||
if (Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress == Memory) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Hob.Raw = GET_NEXT_HOB (Hob);
|
|
||||||
Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw);
|
|
||||||
}
|
|
||||||
ASSERT (Hob.Raw != NULL);
|
|
||||||
if (SkipBeforeMemHob) {
|
|
||||||
//
|
|
||||||
// Use this HOB as aligned mem HOB as there is no portion before it.
|
|
||||||
//
|
|
||||||
HobLength = EFI_PAGES_TO_SIZE(Pages);
|
|
||||||
Hob.MemoryAllocation->AllocDescriptor.MemoryLength = HobLength;
|
|
||||||
} else {
|
} else {
|
||||||
//
|
//
|
||||||
// Use this HOB as before mem HOB and create a new HOB for the aligned portion
|
// Do not over-allocate pages in this case.
|
||||||
//
|
//
|
||||||
HobLength = (AlignedMemory - Memory);
|
Status = PeiServicesAllocatePages (MemoryType, Pages, &Memory);
|
||||||
Hob.MemoryAllocation->AllocDescriptor.MemoryLength = HobLength;
|
if (EFI_ERROR (Status)) {
|
||||||
Hob.MemoryAllocation->AllocDescriptor.MemoryType = EfiConventionalMemory;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
AlignedMemory = (UINTN) Memory;
|
||||||
HobBaseAddress = Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress;
|
|
||||||
HobMemoryType = Hob.MemoryAllocation->AllocDescriptor.MemoryType;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Build the aligned mem HOB if needed
|
|
||||||
//
|
|
||||||
if (!SkipBeforeMemHob) {
|
|
||||||
DEBUG((DEBUG_INFO, "Updated before-mem HOB with BaseAddress = %LX, Length = %LX, MemoryType = %d \n",
|
|
||||||
HobBaseAddress, HobLength, (UINTN) HobMemoryType));
|
|
||||||
|
|
||||||
HobBaseAddress = AlignedMemory;
|
|
||||||
HobLength = EFI_PAGES_TO_SIZE(Pages);
|
|
||||||
HobMemoryType = MemoryType;
|
|
||||||
|
|
||||||
BuildMemoryAllocationHob (
|
|
||||||
HobBaseAddress,
|
|
||||||
HobLength,
|
|
||||||
HobMemoryType
|
|
||||||
);
|
|
||||||
|
|
||||||
DEBUG((DEBUG_INFO, "Created aligned-mem HOB with BaseAddress = %LX, Length = %LX, MemoryType = %d \n",
|
|
||||||
HobBaseAddress, HobLength, (UINTN) HobMemoryType));
|
|
||||||
} else {
|
|
||||||
if (HobBaseAddress != 0) {
|
|
||||||
DEBUG((DEBUG_INFO, "Updated aligned-mem HOB with BaseAddress = %LX, Length = %LX, MemoryType = %d \n",
|
|
||||||
HobBaseAddress, HobLength, (UINTN) HobMemoryType));
|
|
||||||
}
|
}
|
||||||
}
|
return (VOID *) AlignedMemory;
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Build the after mem HOB if needed
|
|
||||||
//
|
|
||||||
if (!SkipAfterMemHob) {
|
|
||||||
HobBaseAddress = AlignedMemory + EFI_PAGES_TO_SIZE(Pages);
|
|
||||||
HobLength = (Memory + EFI_PAGES_TO_SIZE(TotalPages)) - (AlignedMemory + EFI_PAGES_TO_SIZE(Pages));
|
|
||||||
HobMemoryType = EfiConventionalMemory;
|
|
||||||
|
|
||||||
BuildMemoryAllocationHob (
|
|
||||||
HobBaseAddress,
|
|
||||||
HobLength,
|
|
||||||
HobMemoryType
|
|
||||||
);
|
|
||||||
|
|
||||||
DEBUG((DEBUG_INFO, "Created after-mem HOB with BaseAddress = %LX, Length = %LX, MemoryType = %d \n",
|
|
||||||
HobBaseAddress, HobLength, (UINTN) HobMemoryType));
|
|
||||||
}
|
|
||||||
|
|
||||||
return (VOID *) (UINTN) AlignedMemory;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user