mirror of https://github.com/acidanthera/audk.git
MdeModule PeiCore: Support pre memory page allocation
Support pre memory page allocation. Support FreePages. Allocation made prior to permanent memory will be migrated to permanent memory and the HOB updated. Cc: Liming Gao <liming.gao@intel.com> Cc: Ruiyu Ni <Ruiyu.Ni@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
9f43484ce9
commit
b2374cecb0
|
@ -682,13 +682,13 @@ PeiCheckAndSwitchStack (
|
|||
&& (*StackPointer == INIT_CAR_VALUE);
|
||||
StackPointer ++);
|
||||
|
||||
DEBUG ((EFI_D_INFO, "Temp Stack : BaseAddress=0x%p Length=0x%X\n", SecCoreData->StackBase, (UINT32)SecCoreData->StackSize));
|
||||
DEBUG ((EFI_D_INFO, "Temp Heap : BaseAddress=0x%p Length=0x%X\n", Private->HobList.Raw, (UINT32)((UINTN) Private->HobList.HandoffInformationTable->EfiFreeMemoryTop - (UINTN) Private->HobList.Raw)));
|
||||
DEBUG ((EFI_D_INFO, "Total temporary memory: %d bytes.\n", (UINT32)SecCoreData->TemporaryRamSize));
|
||||
DEBUG ((EFI_D_INFO, " temporary memory stack ever used: %d bytes.\n",
|
||||
DEBUG ((DEBUG_INFO, "Temp Stack : BaseAddress=0x%p Length=0x%X\n", SecCoreData->StackBase, (UINT32)SecCoreData->StackSize));
|
||||
DEBUG ((DEBUG_INFO, "Temp Heap : BaseAddress=0x%p Length=0x%X\n", SecCoreData->PeiTemporaryRamBase, (UINT32)SecCoreData->PeiTemporaryRamSize));
|
||||
DEBUG ((DEBUG_INFO, "Total temporary memory: %d bytes.\n", (UINT32)SecCoreData->TemporaryRamSize));
|
||||
DEBUG ((DEBUG_INFO, " temporary memory stack ever used: %d bytes.\n",
|
||||
(UINT32)(SecCoreData->StackSize - ((UINTN) StackPointer - (UINTN)SecCoreData->StackBase))
|
||||
));
|
||||
DEBUG ((EFI_D_INFO, " temporary memory heap used: %d bytes.\n",
|
||||
DEBUG ((DEBUG_INFO, " temporary memory heap used for HobList: %d bytes.\n",
|
||||
(UINT32)((UINTN)Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom - (UINTN)Private->HobList.Raw)
|
||||
));
|
||||
DEBUG_CODE_END ();
|
||||
|
@ -800,16 +800,28 @@ PeiCheckAndSwitchStack (
|
|||
TemporaryRamSize
|
||||
);
|
||||
|
||||
//
|
||||
// Migrate memory pages allocated in pre-memory phase.
|
||||
// It could not be called before calling TemporaryRamSupportPpi->TemporaryRamMigration()
|
||||
// as the migrated memory pages may be overridden by TemporaryRamSupportPpi->TemporaryRamMigration().
|
||||
//
|
||||
MigrateMemoryPages (Private, TRUE);
|
||||
|
||||
//
|
||||
// Entry PEI Phase 2
|
||||
//
|
||||
PeiCore (SecCoreData, NULL, Private);
|
||||
} else {
|
||||
//
|
||||
// Migrate memory pages allocated in pre-memory phase.
|
||||
//
|
||||
MigrateMemoryPages (Private, FALSE);
|
||||
|
||||
//
|
||||
// Migrate the PEI Services Table pointer from temporary RAM to permanent RAM.
|
||||
//
|
||||
MigratePeiServicesTablePointer ();
|
||||
|
||||
|
||||
//
|
||||
// Heap Offset
|
||||
//
|
||||
|
@ -837,7 +849,7 @@ PeiCheckAndSwitchStack (
|
|||
//
|
||||
HeapTemporaryRamSize = (UINTN) (Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom - Private->HobList.HandoffInformationTable->EfiMemoryBottom);
|
||||
ASSERT (BaseOfNewHeap + HeapTemporaryRamSize <= Private->FreePhysicalMemoryTop);
|
||||
CopyMem ((UINT8 *) (UINTN) BaseOfNewHeap, (UINT8 *) PeiTemporaryRamBase, HeapTemporaryRamSize);
|
||||
CopyMem ((UINT8 *) (UINTN) BaseOfNewHeap, PeiTemporaryRamBase, HeapTemporaryRamSize);
|
||||
|
||||
//
|
||||
// Migrate Stack
|
||||
|
@ -846,7 +858,6 @@ PeiCheckAndSwitchStack (
|
|||
|
||||
//
|
||||
// Copy Hole Range Data
|
||||
// Convert PPI from Hole.
|
||||
//
|
||||
if (HoleMemSize != 0) {
|
||||
//
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/** @file
|
||||
EFI PEI Core memory services
|
||||
|
||||
Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2006 - 2017, 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
|
||||
|
@ -110,18 +110,387 @@ PeiInstallPeiMemory (
|
|||
}
|
||||
|
||||
/**
|
||||
The purpose of the service is to publish an interface that allows
|
||||
Migrate memory pages allocated in pre-memory phase.
|
||||
Copy memory pages at temporary heap top to permanent heap top.
|
||||
|
||||
@param[in] Private Pointer to the private data passed in from caller.
|
||||
@param[in] TemporaryRamMigrated Temporary memory has been migrated to permanent memory.
|
||||
|
||||
**/
|
||||
VOID
|
||||
MigrateMemoryPages (
|
||||
IN PEI_CORE_INSTANCE *Private,
|
||||
IN BOOLEAN TemporaryRamMigrated
|
||||
)
|
||||
{
|
||||
EFI_PHYSICAL_ADDRESS NewMemPagesBase;
|
||||
EFI_PHYSICAL_ADDRESS MemPagesBase;
|
||||
|
||||
Private->MemoryPages.Size = (UINTN) (Private->HobList.HandoffInformationTable->EfiMemoryTop -
|
||||
Private->HobList.HandoffInformationTable->EfiFreeMemoryTop);
|
||||
if (Private->MemoryPages.Size == 0) {
|
||||
//
|
||||
// No any memory page allocated in pre-memory phase.
|
||||
//
|
||||
return;
|
||||
}
|
||||
Private->MemoryPages.Base = Private->HobList.HandoffInformationTable->EfiFreeMemoryTop;
|
||||
|
||||
ASSERT (Private->MemoryPages.Size <= Private->FreePhysicalMemoryTop);
|
||||
NewMemPagesBase = Private->FreePhysicalMemoryTop - Private->MemoryPages.Size;
|
||||
NewMemPagesBase &= ~(UINT64)EFI_PAGE_MASK;
|
||||
ASSERT (NewMemPagesBase >= Private->PhysicalMemoryBegin);
|
||||
//
|
||||
// Copy memory pages at temporary heap top to permanent heap top.
|
||||
//
|
||||
if (TemporaryRamMigrated) {
|
||||
//
|
||||
// Memory pages at temporary heap top has been migrated to permanent heap,
|
||||
// Here still needs to copy them from permanent heap to permanent heap top.
|
||||
//
|
||||
MemPagesBase = Private->MemoryPages.Base;
|
||||
if (Private->HeapOffsetPositive) {
|
||||
MemPagesBase += Private->HeapOffset;
|
||||
} else {
|
||||
MemPagesBase -= Private->HeapOffset;
|
||||
}
|
||||
CopyMem ((VOID *)(UINTN)NewMemPagesBase, (VOID *)(UINTN)MemPagesBase, Private->MemoryPages.Size);
|
||||
} else {
|
||||
CopyMem ((VOID *)(UINTN)NewMemPagesBase, (VOID *)(UINTN)Private->MemoryPages.Base, Private->MemoryPages.Size);
|
||||
}
|
||||
|
||||
if (NewMemPagesBase >= Private->MemoryPages.Base) {
|
||||
Private->MemoryPages.OffsetPositive = TRUE;
|
||||
Private->MemoryPages.Offset = (UINTN)(NewMemPagesBase - Private->MemoryPages.Base);
|
||||
} else {
|
||||
Private->MemoryPages.OffsetPositive = FALSE;
|
||||
Private->MemoryPages.Offset = (UINTN)(Private->MemoryPages.Base - NewMemPagesBase);
|
||||
}
|
||||
|
||||
DEBUG ((DEBUG_INFO, "Pages Offset = 0x%lX\n", (UINT64) Private->MemoryPages.Offset));
|
||||
|
||||
Private->FreePhysicalMemoryTop = NewMemPagesBase;
|
||||
}
|
||||
|
||||
/**
|
||||
Migrate MemoryBaseAddress in memory allocation HOBs
|
||||
from the temporary memory to PEI installed memory.
|
||||
|
||||
@param[in] PrivateData Pointer to PeiCore's private data structure.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ConvertMemoryAllocationHobs (
|
||||
IN PEI_CORE_INSTANCE *PrivateData
|
||||
)
|
||||
{
|
||||
EFI_PEI_HOB_POINTERS Hob;
|
||||
EFI_HOB_MEMORY_ALLOCATION *MemoryAllocationHob;
|
||||
EFI_PHYSICAL_ADDRESS OldMemPagesBase;
|
||||
UINTN OldMemPagesSize;
|
||||
|
||||
if (PrivateData->MemoryPages.Size == 0) {
|
||||
//
|
||||
// No any memory page allocated in pre-memory phase.
|
||||
//
|
||||
return;
|
||||
}
|
||||
|
||||
OldMemPagesBase = PrivateData->MemoryPages.Base;
|
||||
OldMemPagesSize = PrivateData->MemoryPages.Size;
|
||||
|
||||
MemoryAllocationHob = NULL;
|
||||
Hob.Raw = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION);
|
||||
while (Hob.Raw != NULL) {
|
||||
MemoryAllocationHob = (EFI_HOB_MEMORY_ALLOCATION *) Hob.Raw;
|
||||
if ((MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress >= OldMemPagesBase) &&
|
||||
(MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress < (OldMemPagesBase + OldMemPagesSize))
|
||||
) {
|
||||
if (PrivateData->MemoryPages.OffsetPositive) {
|
||||
MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress += PrivateData->MemoryPages.Offset;
|
||||
} else {
|
||||
MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress -= PrivateData->MemoryPages.Offset;
|
||||
}
|
||||
}
|
||||
|
||||
Hob.Raw = GET_NEXT_HOB (Hob);
|
||||
Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Internal function to build a HOB for the memory allocation.
|
||||
It will search and reuse the unused(freed) memory allocation HOB,
|
||||
or build memory allocation HOB normally if no unused(freed) memory allocation HOB found.
|
||||
|
||||
@param[in] BaseAddress The 64 bit physical address of the memory.
|
||||
@param[in] Length The length of the memory allocation in bytes.
|
||||
@param[in] MemoryType The type of memory allocated by this HOB.
|
||||
|
||||
**/
|
||||
VOID
|
||||
InternalBuildMemoryAllocationHob (
|
||||
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
||||
IN UINT64 Length,
|
||||
IN EFI_MEMORY_TYPE MemoryType
|
||||
)
|
||||
{
|
||||
EFI_PEI_HOB_POINTERS Hob;
|
||||
EFI_HOB_MEMORY_ALLOCATION *MemoryAllocationHob;
|
||||
|
||||
//
|
||||
// Search unused(freed) memory allocation HOB.
|
||||
//
|
||||
MemoryAllocationHob = NULL;
|
||||
Hob.Raw = GetFirstHob (EFI_HOB_TYPE_UNUSED);
|
||||
while (Hob.Raw != NULL) {
|
||||
if (Hob.Header->HobLength == sizeof (EFI_HOB_MEMORY_ALLOCATION)) {
|
||||
MemoryAllocationHob = (EFI_HOB_MEMORY_ALLOCATION *) Hob.Raw;
|
||||
break;
|
||||
}
|
||||
|
||||
Hob.Raw = GET_NEXT_HOB (Hob);
|
||||
Hob.Raw = GetNextHob (EFI_HOB_TYPE_UNUSED, Hob.Raw);
|
||||
}
|
||||
|
||||
if (MemoryAllocationHob != NULL) {
|
||||
//
|
||||
// Reuse the unused(freed) memory allocation HOB.
|
||||
//
|
||||
MemoryAllocationHob->Header.HobType = EFI_HOB_TYPE_MEMORY_ALLOCATION;
|
||||
ZeroMem (&(MemoryAllocationHob->AllocDescriptor.Name), sizeof (EFI_GUID));
|
||||
MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress = BaseAddress;
|
||||
MemoryAllocationHob->AllocDescriptor.MemoryLength = Length;
|
||||
MemoryAllocationHob->AllocDescriptor.MemoryType = MemoryType;
|
||||
//
|
||||
// Zero the reserved space to match HOB spec
|
||||
//
|
||||
ZeroMem (MemoryAllocationHob->AllocDescriptor.Reserved, sizeof (MemoryAllocationHob->AllocDescriptor.Reserved));
|
||||
} else {
|
||||
//
|
||||
// No unused(freed) memory allocation HOB found.
|
||||
// Build memory allocation HOB normally.
|
||||
//
|
||||
BuildMemoryAllocationHob (
|
||||
BaseAddress,
|
||||
Length,
|
||||
MemoryType
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Update or split memory allocation HOB for memory pages allocate and free.
|
||||
|
||||
@param[in, out] MemoryAllocationHob Pointer to the memory allocation HOB
|
||||
that needs to be updated or split.
|
||||
On output, it will be filled with
|
||||
the input Memory, Bytes and MemoryType.
|
||||
@param[in] Memory Memory to allocate or free.
|
||||
@param[in] Bytes Bytes to allocate or free.
|
||||
@param[in] MemoryType EfiConventionalMemory for pages free,
|
||||
others for pages allocate.
|
||||
|
||||
**/
|
||||
VOID
|
||||
UpdateOrSplitMemoryAllocationHob (
|
||||
IN OUT EFI_HOB_MEMORY_ALLOCATION *MemoryAllocationHob,
|
||||
IN EFI_PHYSICAL_ADDRESS Memory,
|
||||
IN UINT64 Bytes,
|
||||
IN EFI_MEMORY_TYPE MemoryType
|
||||
)
|
||||
{
|
||||
if ((Memory + Bytes) <
|
||||
(MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress + MemoryAllocationHob->AllocDescriptor.MemoryLength)) {
|
||||
//
|
||||
// Last pages need to be split out.
|
||||
//
|
||||
InternalBuildMemoryAllocationHob (
|
||||
Memory + Bytes,
|
||||
(MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress + MemoryAllocationHob->AllocDescriptor.MemoryLength) - (Memory + Bytes),
|
||||
MemoryAllocationHob->AllocDescriptor.MemoryType
|
||||
);
|
||||
}
|
||||
|
||||
if (Memory > MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress) {
|
||||
//
|
||||
// First pages need to be split out.
|
||||
//
|
||||
InternalBuildMemoryAllocationHob (
|
||||
MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress,
|
||||
Memory - MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress,
|
||||
MemoryAllocationHob->AllocDescriptor.MemoryType
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// Update the memory allocation HOB.
|
||||
//
|
||||
MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress = Memory;
|
||||
MemoryAllocationHob->AllocDescriptor.MemoryLength = Bytes;
|
||||
MemoryAllocationHob->AllocDescriptor.MemoryType = MemoryType;
|
||||
}
|
||||
|
||||
/**
|
||||
Merge adjacent free memory ranges in memory allocation HOBs.
|
||||
|
||||
@retval TRUE There are free memory ranges merged.
|
||||
@retval FALSE No free memory ranges merged.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
MergeFreeMemoryInMemoryAllocationHob (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EFI_PEI_HOB_POINTERS Hob;
|
||||
EFI_PEI_HOB_POINTERS Hob2;
|
||||
EFI_HOB_MEMORY_ALLOCATION *MemoryHob;
|
||||
EFI_HOB_MEMORY_ALLOCATION *MemoryHob2;
|
||||
UINT64 Start;
|
||||
UINT64 End;
|
||||
BOOLEAN Merged;
|
||||
|
||||
Merged = FALSE;
|
||||
|
||||
Hob.Raw = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION);
|
||||
while (Hob.Raw != NULL) {
|
||||
if (Hob.MemoryAllocation->AllocDescriptor.MemoryType == EfiConventionalMemory) {
|
||||
MemoryHob = (EFI_HOB_MEMORY_ALLOCATION *) Hob.Raw;
|
||||
Start = MemoryHob->AllocDescriptor.MemoryBaseAddress;
|
||||
End = MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength;
|
||||
|
||||
Hob2.Raw = GET_NEXT_HOB (Hob);
|
||||
Hob2.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw);
|
||||
while (Hob2.Raw != NULL) {
|
||||
if (Hob2.MemoryAllocation->AllocDescriptor.MemoryType == EfiConventionalMemory) {
|
||||
MemoryHob2 = (EFI_HOB_MEMORY_ALLOCATION *) Hob2.Raw;
|
||||
if (Start == (MemoryHob2->AllocDescriptor.MemoryBaseAddress + MemoryHob2->AllocDescriptor.MemoryLength)) {
|
||||
//
|
||||
// Merge adjacent two free memory ranges.
|
||||
//
|
||||
MemoryHob2->AllocDescriptor.MemoryLength += MemoryHob->AllocDescriptor.MemoryLength;
|
||||
Merged = TRUE;
|
||||
//
|
||||
// Mark MemoryHob to be unused(freed).
|
||||
//
|
||||
MemoryHob->Header.HobType = EFI_HOB_TYPE_UNUSED;
|
||||
break;
|
||||
} else if (End == MemoryHob2->AllocDescriptor.MemoryBaseAddress) {
|
||||
//
|
||||
// Merge adjacent two free memory ranges.
|
||||
//
|
||||
MemoryHob2->AllocDescriptor.MemoryBaseAddress = MemoryHob->AllocDescriptor.MemoryBaseAddress;
|
||||
MemoryHob2->AllocDescriptor.MemoryLength += MemoryHob->AllocDescriptor.MemoryLength;
|
||||
Merged = TRUE;
|
||||
//
|
||||
// Mark MemoryHob to be unused(freed).
|
||||
//
|
||||
MemoryHob->Header.HobType = EFI_HOB_TYPE_UNUSED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Hob2.Raw = GET_NEXT_HOB (Hob2);
|
||||
Hob2.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob2.Raw);
|
||||
}
|
||||
}
|
||||
Hob.Raw = GET_NEXT_HOB (Hob);
|
||||
Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw);
|
||||
}
|
||||
|
||||
return Merged;
|
||||
}
|
||||
|
||||
/**
|
||||
Find free memory by searching memory allocation HOBs.
|
||||
|
||||
@param[in] MemoryType The type of memory to allocate.
|
||||
@param[in] Pages The number of contiguous 4 KB pages to allocate.
|
||||
@param[in] Granularity Page allocation granularity.
|
||||
@param[out] Memory Pointer to a physical address. On output, the address is set to the base
|
||||
of the page range that was allocated.
|
||||
|
||||
@retval EFI_SUCCESS The memory range was successfully allocated.
|
||||
@retval EFI_NOT_FOUND No memory allocation HOB with big enough free memory found.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
FindFreeMemoryFromMemoryAllocationHob (
|
||||
IN EFI_MEMORY_TYPE MemoryType,
|
||||
IN UINTN Pages,
|
||||
IN UINTN Granularity,
|
||||
OUT EFI_PHYSICAL_ADDRESS *Memory
|
||||
)
|
||||
{
|
||||
EFI_PEI_HOB_POINTERS Hob;
|
||||
EFI_HOB_MEMORY_ALLOCATION *MemoryAllocationHob;
|
||||
UINT64 Bytes;
|
||||
EFI_PHYSICAL_ADDRESS BaseAddress;
|
||||
|
||||
Bytes = LShiftU64 (Pages, EFI_PAGE_SHIFT);
|
||||
|
||||
BaseAddress = 0;
|
||||
MemoryAllocationHob = NULL;
|
||||
Hob.Raw = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION);
|
||||
while (Hob.Raw != NULL) {
|
||||
if ((Hob.MemoryAllocation->AllocDescriptor.MemoryType == EfiConventionalMemory) &&
|
||||
(Hob.MemoryAllocation->AllocDescriptor.MemoryLength >= Bytes)) {
|
||||
//
|
||||
// Found one memory allocation HOB with big enough free memory.
|
||||
//
|
||||
MemoryAllocationHob = (EFI_HOB_MEMORY_ALLOCATION *) Hob.Raw;
|
||||
BaseAddress = MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress +
|
||||
MemoryAllocationHob->AllocDescriptor.MemoryLength - Bytes;
|
||||
//
|
||||
// Make sure the granularity could be satisfied.
|
||||
//
|
||||
BaseAddress &= ~((EFI_PHYSICAL_ADDRESS) Granularity - 1);
|
||||
if (BaseAddress >= MemoryAllocationHob->AllocDescriptor.MemoryBaseAddress) {
|
||||
break;
|
||||
}
|
||||
BaseAddress = 0;
|
||||
MemoryAllocationHob = NULL;
|
||||
}
|
||||
//
|
||||
// Continue to find.
|
||||
//
|
||||
Hob.Raw = GET_NEXT_HOB (Hob);
|
||||
Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw);
|
||||
}
|
||||
|
||||
if (MemoryAllocationHob != NULL) {
|
||||
UpdateOrSplitMemoryAllocationHob (MemoryAllocationHob, BaseAddress, Bytes, MemoryType);
|
||||
*Memory = BaseAddress;
|
||||
return EFI_SUCCESS;
|
||||
} else {
|
||||
if (MergeFreeMemoryInMemoryAllocationHob ()) {
|
||||
//
|
||||
// Retry if there are free memory ranges merged.
|
||||
//
|
||||
return FindFreeMemoryFromMemoryAllocationHob (MemoryType, Pages, Granularity, Memory);
|
||||
}
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
The purpose of the service is to publish an interface that allows
|
||||
PEIMs to allocate memory ranges that are managed by the PEI Foundation.
|
||||
|
||||
Prior to InstallPeiMemory() being called, PEI will allocate pages from the heap.
|
||||
After InstallPeiMemory() is called, PEI will allocate pages within the region
|
||||
of memory provided by InstallPeiMemory() service in a best-effort fashion.
|
||||
Location-specific allocations are not managed by the PEI foundation code.
|
||||
|
||||
@param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
|
||||
@param MemoryType The type of memory to allocate.
|
||||
@param Pages The number of contiguous 4 KB pages to allocate.
|
||||
@param Memory Pointer to a physical address. On output, the address is set to the base
|
||||
@param Memory Pointer to a physical address. On output, the address is set to the base
|
||||
of the page range that was allocated.
|
||||
|
||||
@retval EFI_SUCCESS The memory range was successfully allocated.
|
||||
@retval EFI_OUT_OF_RESOURCES The pages could not be allocated.
|
||||
@retval EFI_INVALID_PARAMETER Type is not equal to EfiLoaderCode, EfiLoaderData, EfiRuntimeServicesCode,
|
||||
@retval EFI_INVALID_PARAMETER Type is not equal to EfiLoaderCode, EfiLoaderData, EfiRuntimeServicesCode,
|
||||
EfiRuntimeServicesData, EfiBootServicesCode, EfiBootServicesData,
|
||||
EfiACPIReclaimMemory, EfiReservedMemoryType, or EfiACPIMemoryNVS.
|
||||
|
||||
|
@ -135,6 +504,7 @@ PeiAllocatePages (
|
|||
OUT EFI_PHYSICAL_ADDRESS *Memory
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
PEI_CORE_INSTANCE *PrivateData;
|
||||
EFI_PEI_HOB_POINTERS Hob;
|
||||
EFI_PHYSICAL_ADDRESS *FreeMemoryTop;
|
||||
|
@ -157,6 +527,16 @@ PeiAllocatePages (
|
|||
|
||||
Granularity = DEFAULT_PAGE_ALLOCATION_GRANULARITY;
|
||||
|
||||
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
|
||||
Hob.Raw = PrivateData->HobList.Raw;
|
||||
|
||||
if (Hob.Raw == NULL) {
|
||||
//
|
||||
// HOB is not initialized yet.
|
||||
//
|
||||
return EFI_NOT_AVAILABLE_YET;
|
||||
}
|
||||
|
||||
if (RUNTIME_PAGE_ALLOCATION_GRANULARITY > DEFAULT_PAGE_ALLOCATION_GRANULARITY &&
|
||||
(MemoryType == EfiACPIReclaimMemory ||
|
||||
MemoryType == EfiACPIMemoryNVS ||
|
||||
|
@ -169,23 +549,13 @@ PeiAllocatePages (
|
|||
Granularity / SIZE_1KB));
|
||||
}
|
||||
|
||||
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
|
||||
Hob.Raw = PrivateData->HobList.Raw;
|
||||
|
||||
//
|
||||
// Check if Hob already available
|
||||
//
|
||||
if (!PrivateData->PeiMemoryInstalled) {
|
||||
if (!PrivateData->PeiMemoryInstalled && PrivateData->SwitchStackSignal) {
|
||||
//
|
||||
// When PeiInstallMemory is called but temporary memory has *not* been moved to temporary memory,
|
||||
// When PeiInstallMemory is called but temporary memory has *not* been moved to permanent memory,
|
||||
// the AllocatePage will depend on the field of PEI_CORE_INSTANCE structure.
|
||||
//
|
||||
if (!PrivateData->SwitchStackSignal) {
|
||||
return EFI_NOT_AVAILABLE_YET;
|
||||
} else {
|
||||
FreeMemoryTop = &(PrivateData->FreePhysicalMemoryTop);
|
||||
FreeMemoryBottom = &(PrivateData->PhysicalMemoryBegin);
|
||||
}
|
||||
FreeMemoryTop = &(PrivateData->FreePhysicalMemoryTop);
|
||||
FreeMemoryBottom = &(PrivateData->PhysicalMemoryBegin);
|
||||
} else {
|
||||
FreeMemoryTop = &(Hob.HandoffInformationTable->EfiFreeMemoryTop);
|
||||
FreeMemoryBottom = &(Hob.HandoffInformationTable->EfiFreeMemoryBottom);
|
||||
|
@ -207,7 +577,7 @@ PeiAllocatePages (
|
|||
// Create a memory allocation HOB to cover
|
||||
// the pages that we will lose to rounding
|
||||
//
|
||||
BuildMemoryAllocationHob (
|
||||
InternalBuildMemoryAllocationHob (
|
||||
*(FreeMemoryTop),
|
||||
Padding & ~(UINTN)EFI_PAGE_MASK,
|
||||
EfiConventionalMemory
|
||||
|
@ -216,18 +586,20 @@ PeiAllocatePages (
|
|||
|
||||
//
|
||||
// Verify that there is sufficient memory to satisfy the allocation.
|
||||
// For page allocation, the overhead sizeof (EFI_HOB_MEMORY_ALLOCATION) needs to be considered.
|
||||
//
|
||||
if ((UINTN) (*FreeMemoryTop - *FreeMemoryBottom) < (UINTN) ALIGN_VALUE (sizeof (EFI_HOB_MEMORY_ALLOCATION), 8)) {
|
||||
DEBUG ((EFI_D_ERROR, "AllocatePages failed: No space to build memory allocation hob.\n"));
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
RemainingPages = (UINTN)(*FreeMemoryTop - *FreeMemoryBottom - ALIGN_VALUE (sizeof (EFI_HOB_MEMORY_ALLOCATION), 8)) >> EFI_PAGE_SHIFT;
|
||||
RemainingPages = (UINTN)(*FreeMemoryTop - *FreeMemoryBottom) >> EFI_PAGE_SHIFT;
|
||||
//
|
||||
// The number of remaining pages needs to be greater than or equal to that of the request pages.
|
||||
//
|
||||
Pages = ALIGN_VALUE (Pages, EFI_SIZE_TO_PAGES (Granularity));
|
||||
if (RemainingPages < Pages) {
|
||||
//
|
||||
// Try to find free memory by searching memory allocation HOBs.
|
||||
//
|
||||
Status = FindFreeMemoryFromMemoryAllocationHob (MemoryType, Pages, Granularity, Memory);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
DEBUG ((EFI_D_ERROR, "AllocatePages failed: No 0x%lx Pages is available.\n", (UINT64) Pages));
|
||||
DEBUG ((EFI_D_ERROR, "There is only left 0x%lx pages memory resource to be allocated.\n", (UINT64) RemainingPages));
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
|
@ -245,7 +617,7 @@ PeiAllocatePages (
|
|||
//
|
||||
// Create a memory allocation HOB.
|
||||
//
|
||||
BuildMemoryAllocationHob (
|
||||
InternalBuildMemoryAllocationHob (
|
||||
*(FreeMemoryTop),
|
||||
Pages * EFI_PAGE_SIZE,
|
||||
MemoryType
|
||||
|
@ -255,6 +627,141 @@ PeiAllocatePages (
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Mark the memory allocation HOB to be unused(freed) and update *FreeMemoryTop
|
||||
if MemoryBaseAddress == *FreeMemoryTop.
|
||||
|
||||
@param[in] PrivateData Pointer to PeiCore's private data structure.
|
||||
@param[in, out] MemoryAllocationHobToFree Pointer to memory allocation HOB to be freed.
|
||||
|
||||
**/
|
||||
VOID
|
||||
FreeMemoryAllocationHob (
|
||||
IN PEI_CORE_INSTANCE *PrivateData,
|
||||
IN OUT EFI_HOB_MEMORY_ALLOCATION *MemoryAllocationHobToFree
|
||||
)
|
||||
{
|
||||
EFI_PEI_HOB_POINTERS Hob;
|
||||
EFI_PHYSICAL_ADDRESS *FreeMemoryTop;
|
||||
EFI_HOB_MEMORY_ALLOCATION *MemoryAllocationHob;
|
||||
|
||||
Hob.Raw = PrivateData->HobList.Raw;
|
||||
|
||||
if (!PrivateData->PeiMemoryInstalled && PrivateData->SwitchStackSignal) {
|
||||
//
|
||||
// When PeiInstallMemory is called but temporary memory has *not* been moved to permanent memory,
|
||||
// use the FreePhysicalMemoryTop field of PEI_CORE_INSTANCE structure.
|
||||
//
|
||||
FreeMemoryTop = &(PrivateData->FreePhysicalMemoryTop);
|
||||
} else {
|
||||
FreeMemoryTop = &(Hob.HandoffInformationTable->EfiFreeMemoryTop);
|
||||
}
|
||||
|
||||
if (MemoryAllocationHobToFree->AllocDescriptor.MemoryBaseAddress == *FreeMemoryTop) {
|
||||
//
|
||||
// Update *FreeMemoryTop.
|
||||
//
|
||||
*FreeMemoryTop += MemoryAllocationHobToFree->AllocDescriptor.MemoryLength;
|
||||
//
|
||||
// Mark the memory allocation HOB to be unused(freed).
|
||||
//
|
||||
MemoryAllocationHobToFree->Header.HobType = EFI_HOB_TYPE_UNUSED;
|
||||
|
||||
MemoryAllocationHob = NULL;
|
||||
Hob.Raw = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION);
|
||||
while (Hob.Raw != NULL) {
|
||||
if ((Hob.MemoryAllocation->AllocDescriptor.MemoryType == EfiConventionalMemory) &&
|
||||
(Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress == *FreeMemoryTop)) {
|
||||
//
|
||||
// Found memory allocation HOB that has EfiConventionalMemory MemoryType and
|
||||
// MemoryBaseAddress == new *FreeMemoryTop.
|
||||
//
|
||||
MemoryAllocationHob = (EFI_HOB_MEMORY_ALLOCATION *) Hob.Raw;
|
||||
break;
|
||||
}
|
||||
Hob.Raw = GET_NEXT_HOB (Hob);
|
||||
Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw);
|
||||
}
|
||||
//
|
||||
// Free memory allocation HOB iteratively.
|
||||
//
|
||||
if (MemoryAllocationHob != NULL) {
|
||||
FreeMemoryAllocationHob (PrivateData, MemoryAllocationHob);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Frees memory pages.
|
||||
|
||||
@param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
|
||||
@param[in] Memory The base physical address of the pages to be freed.
|
||||
@param[in] Pages The number of contiguous 4 KB pages to free.
|
||||
|
||||
@retval EFI_SUCCESS The requested pages were freed.
|
||||
@retval EFI_INVALID_PARAMETER Memory is not a page-aligned address or Pages is invalid.
|
||||
@retval EFI_NOT_FOUND The requested memory pages were not allocated with
|
||||
AllocatePages().
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PeiFreePages (
|
||||
IN CONST EFI_PEI_SERVICES **PeiServices,
|
||||
IN EFI_PHYSICAL_ADDRESS Memory,
|
||||
IN UINTN Pages
|
||||
)
|
||||
{
|
||||
PEI_CORE_INSTANCE *PrivateData;
|
||||
UINT64 Bytes;
|
||||
UINT64 Start;
|
||||
UINT64 End;
|
||||
EFI_PEI_HOB_POINTERS Hob;
|
||||
EFI_HOB_MEMORY_ALLOCATION *MemoryAllocationHob;
|
||||
|
||||
Bytes = LShiftU64 (Pages, EFI_PAGE_SHIFT);
|
||||
Start = Memory;
|
||||
End = Start + Bytes - 1;
|
||||
|
||||
if (Pages == 0 || ((Start & EFI_PAGE_MASK) != 0) || (Start >= End)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
|
||||
Hob.Raw = PrivateData->HobList.Raw;
|
||||
|
||||
if (Hob.Raw == NULL) {
|
||||
//
|
||||
// HOB is not initialized yet.
|
||||
//
|
||||
return EFI_NOT_AVAILABLE_YET;
|
||||
}
|
||||
|
||||
MemoryAllocationHob = NULL;
|
||||
Hob.Raw = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION);
|
||||
while (Hob.Raw != NULL) {
|
||||
if ((Hob.MemoryAllocation->AllocDescriptor.MemoryType != EfiConventionalMemory) &&
|
||||
(Memory >= Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress) &&
|
||||
((Memory + Bytes) <= (Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress + Hob.MemoryAllocation->AllocDescriptor.MemoryLength))) {
|
||||
//
|
||||
// Found the memory allocation HOB that includes the memory pages to be freed.
|
||||
//
|
||||
MemoryAllocationHob = (EFI_HOB_MEMORY_ALLOCATION *) Hob.Raw;
|
||||
break;
|
||||
}
|
||||
Hob.Raw = GET_NEXT_HOB (Hob);
|
||||
Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw);
|
||||
}
|
||||
|
||||
if (MemoryAllocationHob != NULL) {
|
||||
UpdateOrSplitMemoryAllocationHob (MemoryAllocationHob, Memory, Bytes, EfiConventionalMemory);
|
||||
FreeMemoryAllocationHob (PrivateData, MemoryAllocationHob);
|
||||
return EFI_SUCCESS;
|
||||
} else {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Pool allocation service. Before permanent memory is discoveried, the pool will
|
||||
|
|
|
@ -233,6 +233,10 @@ struct _PEI_CORE_INSTANCE {
|
|||
BOOLEAN HeapOffsetPositive;
|
||||
UINTN StackOffset;
|
||||
BOOLEAN StackOffsetPositive;
|
||||
//
|
||||
// Information for migrating memory pages allocated in pre-memory phase.
|
||||
//
|
||||
HOLE_MEMORY_DATA MemoryPages;
|
||||
PEICORE_FUNCTION_POINTER ShadowedPeiCore;
|
||||
CACHE_SECTION_DATA CacheSection;
|
||||
//
|
||||
|
@ -263,7 +267,7 @@ struct _PEI_CORE_INSTANCE {
|
|||
|
||||
//
|
||||
// Temp Memory Range is not covered by PeiTempMem and Stack.
|
||||
// Those Memory Range will be migrated into phisical memory.
|
||||
// Those Memory Range will be migrated into physical memory.
|
||||
//
|
||||
HOLE_MEMORY_DATA HoleData[HOLE_MAX_NUMBER];
|
||||
};
|
||||
|
@ -423,7 +427,7 @@ InitializePpiServices (
|
|||
|
||||
/**
|
||||
|
||||
Migrate the Hob list from the temporary memory stack to PEI installed memory.
|
||||
Migrate the Hob list from the temporary memory to PEI installed memory.
|
||||
|
||||
@param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size
|
||||
and location of temporary RAM, the stack location and the BFV location.
|
||||
|
@ -877,30 +881,81 @@ PeiInstallPeiMemory (
|
|||
);
|
||||
|
||||
/**
|
||||
Migrate memory pages allocated in pre-memory phase.
|
||||
Copy memory pages at temporary heap top to permanent heap top.
|
||||
|
||||
Memory allocation service on permanent memory,
|
||||
not usable prior to the memory installation.
|
||||
@param[in] Private Pointer to the private data passed in from caller.
|
||||
@param[in] TemporaryRamMigrated Temporary memory has been migrated to permanent memory.
|
||||
|
||||
**/
|
||||
VOID
|
||||
MigrateMemoryPages (
|
||||
IN PEI_CORE_INSTANCE *Private,
|
||||
IN BOOLEAN TemporaryRamMigrated
|
||||
);
|
||||
|
||||
@param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
|
||||
@param MemoryType Type of memory to allocate.
|
||||
@param Pages Number of pages to allocate.
|
||||
@param Memory Pointer of memory allocated.
|
||||
/**
|
||||
Migrate MemoryBaseAddress in memory allocation HOBs
|
||||
from the temporary memory to PEI installed memory.
|
||||
|
||||
@retval EFI_SUCCESS The allocation was successful
|
||||
@retval EFI_INVALID_PARAMETER Only AllocateAnyAddress is supported.
|
||||
@retval EFI_NOT_AVAILABLE_YET Called with permanent memory not available
|
||||
@retval EFI_OUT_OF_RESOURCES There is not enough HOB heap to satisfy the requirement
|
||||
to allocate the number of pages.
|
||||
@param[in] PrivateData Pointer to PeiCore's private data structure.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ConvertMemoryAllocationHobs (
|
||||
IN PEI_CORE_INSTANCE *PrivateData
|
||||
);
|
||||
|
||||
/**
|
||||
The purpose of the service is to publish an interface that allows
|
||||
PEIMs to allocate memory ranges that are managed by the PEI Foundation.
|
||||
|
||||
Prior to InstallPeiMemory() being called, PEI will allocate pages from the heap.
|
||||
After InstallPeiMemory() is called, PEI will allocate pages within the region
|
||||
of memory provided by InstallPeiMemory() service in a best-effort fashion.
|
||||
Location-specific allocations are not managed by the PEI foundation code.
|
||||
|
||||
@param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
|
||||
@param MemoryType The type of memory to allocate.
|
||||
@param Pages The number of contiguous 4 KB pages to allocate.
|
||||
@param Memory Pointer to a physical address. On output, the address is set to the base
|
||||
of the page range that was allocated.
|
||||
|
||||
@retval EFI_SUCCESS The memory range was successfully allocated.
|
||||
@retval EFI_OUT_OF_RESOURCES The pages could not be allocated.
|
||||
@retval EFI_INVALID_PARAMETER Type is not equal to EfiLoaderCode, EfiLoaderData, EfiRuntimeServicesCode,
|
||||
EfiRuntimeServicesData, EfiBootServicesCode, EfiBootServicesData,
|
||||
EfiACPIReclaimMemory, EfiReservedMemoryType, or EfiACPIMemoryNVS.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PeiAllocatePages (
|
||||
IN CONST EFI_PEI_SERVICES **PeiServices,
|
||||
IN EFI_MEMORY_TYPE MemoryType,
|
||||
IN UINTN Pages,
|
||||
OUT EFI_PHYSICAL_ADDRESS *Memory
|
||||
IN CONST EFI_PEI_SERVICES **PeiServices,
|
||||
IN EFI_MEMORY_TYPE MemoryType,
|
||||
IN UINTN Pages,
|
||||
OUT EFI_PHYSICAL_ADDRESS *Memory
|
||||
);
|
||||
|
||||
/**
|
||||
Frees memory pages.
|
||||
|
||||
@param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
|
||||
@param[in] Memory The base physical address of the pages to be freed.
|
||||
@param[in] Pages The number of contiguous 4 KB pages to free.
|
||||
|
||||
@retval EFI_SUCCESS The requested pages were freed.
|
||||
@retval EFI_INVALID_PARAMETER Memory is not a page-aligned address or Pages is invalid.
|
||||
@retval EFI_NOT_FOUND The requested memory pages were not allocated with
|
||||
AllocatePages().
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PeiFreePages (
|
||||
IN CONST EFI_PEI_SERVICES **PeiServices,
|
||||
IN EFI_PHYSICAL_ADDRESS Memory,
|
||||
IN UINTN Pages
|
||||
);
|
||||
|
||||
/**
|
||||
|
|
|
@ -64,7 +64,8 @@ EFI_PEI_SERVICES gPs = {
|
|||
PeiRegisterForShadow,
|
||||
PeiFfsFindSectionData3,
|
||||
PeiFfsGetFileInfo2,
|
||||
PeiResetSystem2
|
||||
PeiResetSystem2,
|
||||
PeiFreePages,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -231,6 +232,11 @@ PeiCore (
|
|||
HandoffInformationTable->EfiFreeMemoryTop = OldCoreData->FreePhysicalMemoryTop;
|
||||
HandoffInformationTable->EfiFreeMemoryBottom = HandoffInformationTable->EfiEndOfHobList + sizeof (EFI_HOB_GENERIC_HEADER);
|
||||
|
||||
//
|
||||
// We need convert MemoryBaseAddress in memory allocation HOBs
|
||||
//
|
||||
ConvertMemoryAllocationHobs (OldCoreData);
|
||||
|
||||
//
|
||||
// We need convert the PPI descriptor's pointer
|
||||
//
|
||||
|
|
|
@ -103,7 +103,7 @@ ConvertSinglePpiPointer (
|
|||
|
||||
/**
|
||||
|
||||
Migrate PPI Pointers from the temporary memory stack to PEI installed memory.
|
||||
Migrate PPI Pointers from the temporary memory to PEI installed memory.
|
||||
|
||||
@param SecCoreData Points to a data structure containing SEC to PEI handoff data, such as the size
|
||||
and location of temporary RAM, the stack location and the BFV location.
|
||||
|
@ -121,6 +121,20 @@ ConvertPpiPointers (
|
|||
|
||||
for (Index = 0; Index < PcdGet32 (PcdPeiCoreMaxPpiSupported); Index++) {
|
||||
if (Index < PrivateData->PpiData.PpiListEnd || Index > PrivateData->PpiData.NotifyListEnd) {
|
||||
if (PrivateData->MemoryPages.Size != 0) {
|
||||
//
|
||||
// Convert PPI pointer in old memory pages
|
||||
// It needs to be done before Convert PPI pointer in old Heap
|
||||
//
|
||||
ConvertSinglePpiPointer (
|
||||
&PrivateData->PpiData.PpiListPtrs[Index],
|
||||
(UINTN)PrivateData->MemoryPages.Base,
|
||||
(UINTN)PrivateData->MemoryPages.Base + PrivateData->MemoryPages.Size,
|
||||
PrivateData->MemoryPages.Offset,
|
||||
PrivateData->MemoryPages.OffsetPositive
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// Convert PPI pointer in old Heap
|
||||
//
|
||||
|
|
Loading…
Reference in New Issue