mirror of https://github.com/acidanthera/audk.git
Only reserve the aligned memory instead of reserving the unaligned memory in PeiMemoryAllocationLib
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Gao, Liming <liming.gao@intel.com> Reviewed-by: Michael Kinney <michael.d.kinney@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15878 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
fa7fadf78e
commit
6809c8723e
|
@ -2,7 +2,7 @@
|
|||
Support routines for memory allocation routines
|
||||
based on PeiService for PEI phase drivers.
|
||||
|
||||
Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2006 - 2014, Intel Corporation. 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
|
||||
|
@ -207,8 +207,15 @@ InternalAllocateAlignedPages (
|
|||
IN UINTN Alignment
|
||||
)
|
||||
{
|
||||
VOID *Memory;
|
||||
UINTN AlignmentMask;
|
||||
EFI_PHYSICAL_ADDRESS Memory;
|
||||
EFI_PHYSICAL_ADDRESS AlignedMemory;
|
||||
EFI_PEI_HOB_POINTERS Hob;
|
||||
BOOLEAN SkipBeforeMemHob = FALSE;
|
||||
BOOLEAN SkipAfterMemHob = FALSE;
|
||||
EFI_PHYSICAL_ADDRESS HobBaseAddress;
|
||||
UINT64 HobLength;
|
||||
EFI_MEMORY_TYPE HobMemoryType;
|
||||
UINTN TotalPages;
|
||||
|
||||
//
|
||||
// Alignment must be a power of two or zero.
|
||||
|
@ -221,17 +228,134 @@ InternalAllocateAlignedPages (
|
|||
//
|
||||
// Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
|
||||
//
|
||||
ASSERT (Pages <= (MAX_ADDRESS - EFI_SIZE_TO_PAGES (Alignment)));
|
||||
ASSERT (Pages <= (MAX_ADDRESS - EFI_SIZE_TO_PAGES (Alignment)));
|
||||
|
||||
//
|
||||
// We would rather waste some memory to save PEI code size.
|
||||
// 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).
|
||||
//
|
||||
Memory = InternalAllocatePages (MemoryType, Pages + EFI_SIZE_TO_PAGES (Alignment));
|
||||
if (Alignment == 0) {
|
||||
AlignmentMask = Alignment;
|
||||
} else {
|
||||
AlignmentMask = Alignment - 1;
|
||||
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 (VOID *) (UINTN) (((UINTN) Memory + AlignmentMask) & ~AlignmentMask);
|
||||
DEBUG ((DEBUG_INFO, "Allocated Memory unaligned: Address = 0x%LX, Pages = 0x%X, Type = %d \n", Memory, TotalPages, (UINTN) MemoryType));
|
||||
|
||||
//
|
||||
// Alignment calculation
|
||||
//
|
||||
AlignedMemory = Memory;
|
||||
if (Alignment > EFI_PAGE_SIZE) {
|
||||
AlignedMemory = ALIGN_VALUE (Memory, Alignment);
|
||||
}
|
||||
DEBUG ((DEBUG_INFO, "After aligning to 0x%X bytes: Address = 0x%LX, Pages = 0x%X \n", Alignment, AlignedMemory, Pages));
|
||||
|
||||
//
|
||||
// In general three HOBs cover the total allocated space.
|
||||
// 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"
|
||||
// Aligned mem HOB covers the region between "AlignedMemory" and "AlignedMemory + EFI_PAGES_TO_SIZE(Pages)"
|
||||
// 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.
|
||||
//
|
||||
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 {
|
||||
//
|
||||
// Use this HOB as before mem HOB and create a new HOB for the aligned portion
|
||||
//
|
||||
HobLength = (AlignedMemory - Memory);
|
||||
Hob.MemoryAllocation->AllocDescriptor.MemoryLength = HobLength;
|
||||
Hob.MemoryAllocation->AllocDescriptor.MemoryType = EfiConventionalMemory;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 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…
Reference in New Issue