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 == INIT_CAR_VALUE);
|
||||||
StackPointer ++);
|
StackPointer ++);
|
||||||
|
|
||||||
DEBUG ((EFI_D_INFO, "Temp Stack : BaseAddress=0x%p Length=0x%X\n", SecCoreData->StackBase, (UINT32)SecCoreData->StackSize));
|
DEBUG ((DEBUG_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 ((DEBUG_INFO, "Temp Heap : BaseAddress=0x%p Length=0x%X\n", SecCoreData->PeiTemporaryRamBase, (UINT32)SecCoreData->PeiTemporaryRamSize));
|
||||||
DEBUG ((EFI_D_INFO, "Total temporary memory: %d bytes.\n", (UINT32)SecCoreData->TemporaryRamSize));
|
DEBUG ((DEBUG_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, " temporary memory stack ever used: %d bytes.\n",
|
||||||
(UINT32)(SecCoreData->StackSize - ((UINTN) StackPointer - (UINTN)SecCoreData->StackBase))
|
(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)
|
(UINT32)((UINTN)Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom - (UINTN)Private->HobList.Raw)
|
||||||
));
|
));
|
||||||
DEBUG_CODE_END ();
|
DEBUG_CODE_END ();
|
||||||
@ -800,11 +800,23 @@ PeiCheckAndSwitchStack (
|
|||||||
TemporaryRamSize
|
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
|
// Entry PEI Phase 2
|
||||||
//
|
//
|
||||||
PeiCore (SecCoreData, NULL, Private);
|
PeiCore (SecCoreData, NULL, Private);
|
||||||
} else {
|
} else {
|
||||||
|
//
|
||||||
|
// Migrate memory pages allocated in pre-memory phase.
|
||||||
|
//
|
||||||
|
MigrateMemoryPages (Private, FALSE);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Migrate the PEI Services Table pointer from temporary RAM to permanent RAM.
|
// Migrate the PEI Services Table pointer from temporary RAM to permanent RAM.
|
||||||
//
|
//
|
||||||
@ -837,7 +849,7 @@ PeiCheckAndSwitchStack (
|
|||||||
//
|
//
|
||||||
HeapTemporaryRamSize = (UINTN) (Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom - Private->HobList.HandoffInformationTable->EfiMemoryBottom);
|
HeapTemporaryRamSize = (UINTN) (Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom - Private->HobList.HandoffInformationTable->EfiMemoryBottom);
|
||||||
ASSERT (BaseOfNewHeap + HeapTemporaryRamSize <= Private->FreePhysicalMemoryTop);
|
ASSERT (BaseOfNewHeap + HeapTemporaryRamSize <= Private->FreePhysicalMemoryTop);
|
||||||
CopyMem ((UINT8 *) (UINTN) BaseOfNewHeap, (UINT8 *) PeiTemporaryRamBase, HeapTemporaryRamSize);
|
CopyMem ((UINT8 *) (UINTN) BaseOfNewHeap, PeiTemporaryRamBase, HeapTemporaryRamSize);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Migrate Stack
|
// Migrate Stack
|
||||||
@ -846,7 +858,6 @@ PeiCheckAndSwitchStack (
|
|||||||
|
|
||||||
//
|
//
|
||||||
// Copy Hole Range Data
|
// Copy Hole Range Data
|
||||||
// Convert PPI from Hole.
|
|
||||||
//
|
//
|
||||||
if (HoleMemSize != 0) {
|
if (HoleMemSize != 0) {
|
||||||
//
|
//
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/** @file
|
/** @file
|
||||||
EFI PEI Core memory services
|
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
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
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
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
@ -109,10 +109,379 @@ PeiInstallPeiMemory (
|
|||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
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
|
The purpose of the service is to publish an interface that allows
|
||||||
PEIMs to allocate memory ranges that are managed by the PEI Foundation.
|
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 PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
|
||||||
@param MemoryType The type of memory to allocate.
|
@param MemoryType The type of memory to allocate.
|
||||||
@param Pages The number of contiguous 4 KB pages to allocate.
|
@param Pages The number of contiguous 4 KB pages to allocate.
|
||||||
@ -135,6 +504,7 @@ PeiAllocatePages (
|
|||||||
OUT EFI_PHYSICAL_ADDRESS *Memory
|
OUT EFI_PHYSICAL_ADDRESS *Memory
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
PEI_CORE_INSTANCE *PrivateData;
|
PEI_CORE_INSTANCE *PrivateData;
|
||||||
EFI_PEI_HOB_POINTERS Hob;
|
EFI_PEI_HOB_POINTERS Hob;
|
||||||
EFI_PHYSICAL_ADDRESS *FreeMemoryTop;
|
EFI_PHYSICAL_ADDRESS *FreeMemoryTop;
|
||||||
@ -157,6 +527,16 @@ PeiAllocatePages (
|
|||||||
|
|
||||||
Granularity = DEFAULT_PAGE_ALLOCATION_GRANULARITY;
|
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 &&
|
if (RUNTIME_PAGE_ALLOCATION_GRANULARITY > DEFAULT_PAGE_ALLOCATION_GRANULARITY &&
|
||||||
(MemoryType == EfiACPIReclaimMemory ||
|
(MemoryType == EfiACPIReclaimMemory ||
|
||||||
MemoryType == EfiACPIMemoryNVS ||
|
MemoryType == EfiACPIMemoryNVS ||
|
||||||
@ -169,23 +549,13 @@ PeiAllocatePages (
|
|||||||
Granularity / SIZE_1KB));
|
Granularity / SIZE_1KB));
|
||||||
}
|
}
|
||||||
|
|
||||||
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
|
if (!PrivateData->PeiMemoryInstalled && PrivateData->SwitchStackSignal) {
|
||||||
Hob.Raw = PrivateData->HobList.Raw;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Check if Hob already available
|
|
||||||
//
|
|
||||||
if (!PrivateData->PeiMemoryInstalled) {
|
|
||||||
//
|
//
|
||||||
// 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.
|
// the AllocatePage will depend on the field of PEI_CORE_INSTANCE structure.
|
||||||
//
|
//
|
||||||
if (!PrivateData->SwitchStackSignal) {
|
FreeMemoryTop = &(PrivateData->FreePhysicalMemoryTop);
|
||||||
return EFI_NOT_AVAILABLE_YET;
|
FreeMemoryBottom = &(PrivateData->PhysicalMemoryBegin);
|
||||||
} else {
|
|
||||||
FreeMemoryTop = &(PrivateData->FreePhysicalMemoryTop);
|
|
||||||
FreeMemoryBottom = &(PrivateData->PhysicalMemoryBegin);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
FreeMemoryTop = &(Hob.HandoffInformationTable->EfiFreeMemoryTop);
|
FreeMemoryTop = &(Hob.HandoffInformationTable->EfiFreeMemoryTop);
|
||||||
FreeMemoryBottom = &(Hob.HandoffInformationTable->EfiFreeMemoryBottom);
|
FreeMemoryBottom = &(Hob.HandoffInformationTable->EfiFreeMemoryBottom);
|
||||||
@ -207,7 +577,7 @@ PeiAllocatePages (
|
|||||||
// Create a memory allocation HOB to cover
|
// Create a memory allocation HOB to cover
|
||||||
// the pages that we will lose to rounding
|
// the pages that we will lose to rounding
|
||||||
//
|
//
|
||||||
BuildMemoryAllocationHob (
|
InternalBuildMemoryAllocationHob (
|
||||||
*(FreeMemoryTop),
|
*(FreeMemoryTop),
|
||||||
Padding & ~(UINTN)EFI_PAGE_MASK,
|
Padding & ~(UINTN)EFI_PAGE_MASK,
|
||||||
EfiConventionalMemory
|
EfiConventionalMemory
|
||||||
@ -216,18 +586,20 @@ PeiAllocatePages (
|
|||||||
|
|
||||||
//
|
//
|
||||||
// Verify that there is sufficient memory to satisfy the allocation.
|
// 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)) {
|
RemainingPages = (UINTN)(*FreeMemoryTop - *FreeMemoryBottom) >> EFI_PAGE_SHIFT;
|
||||||
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;
|
|
||||||
//
|
//
|
||||||
// The number of remaining pages needs to be greater than or equal to that of the request pages.
|
// 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));
|
Pages = ALIGN_VALUE (Pages, EFI_SIZE_TO_PAGES (Granularity));
|
||||||
if (RemainingPages < Pages) {
|
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, "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));
|
DEBUG ((EFI_D_ERROR, "There is only left 0x%lx pages memory resource to be allocated.\n", (UINT64) RemainingPages));
|
||||||
return EFI_OUT_OF_RESOURCES;
|
return EFI_OUT_OF_RESOURCES;
|
||||||
@ -245,7 +617,7 @@ PeiAllocatePages (
|
|||||||
//
|
//
|
||||||
// Create a memory allocation HOB.
|
// Create a memory allocation HOB.
|
||||||
//
|
//
|
||||||
BuildMemoryAllocationHob (
|
InternalBuildMemoryAllocationHob (
|
||||||
*(FreeMemoryTop),
|
*(FreeMemoryTop),
|
||||||
Pages * EFI_PAGE_SIZE,
|
Pages * EFI_PAGE_SIZE,
|
||||||
MemoryType
|
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
|
Pool allocation service. Before permanent memory is discoveried, the pool will
|
||||||
|
@ -233,6 +233,10 @@ struct _PEI_CORE_INSTANCE {
|
|||||||
BOOLEAN HeapOffsetPositive;
|
BOOLEAN HeapOffsetPositive;
|
||||||
UINTN StackOffset;
|
UINTN StackOffset;
|
||||||
BOOLEAN StackOffsetPositive;
|
BOOLEAN StackOffsetPositive;
|
||||||
|
//
|
||||||
|
// Information for migrating memory pages allocated in pre-memory phase.
|
||||||
|
//
|
||||||
|
HOLE_MEMORY_DATA MemoryPages;
|
||||||
PEICORE_FUNCTION_POINTER ShadowedPeiCore;
|
PEICORE_FUNCTION_POINTER ShadowedPeiCore;
|
||||||
CACHE_SECTION_DATA CacheSection;
|
CACHE_SECTION_DATA CacheSection;
|
||||||
//
|
//
|
||||||
@ -263,7 +267,7 @@ struct _PEI_CORE_INSTANCE {
|
|||||||
|
|
||||||
//
|
//
|
||||||
// Temp Memory Range is not covered by PeiTempMem and Stack.
|
// 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];
|
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
|
@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.
|
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,
|
@param[in] Private Pointer to the private data passed in from caller.
|
||||||
not usable prior to the memory installation.
|
@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.
|
Migrate MemoryBaseAddress in memory allocation HOBs
|
||||||
@param Pages Number of pages to allocate.
|
from the temporary memory to PEI installed memory.
|
||||||
@param Memory Pointer of memory allocated.
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The allocation was successful
|
@param[in] PrivateData Pointer to PeiCore's private data structure.
|
||||||
@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
|
VOID
|
||||||
to allocate the number of pages.
|
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
|
EFI_STATUS
|
||||||
EFIAPI
|
EFIAPI
|
||||||
PeiAllocatePages (
|
PeiAllocatePages (
|
||||||
IN CONST EFI_PEI_SERVICES **PeiServices,
|
IN CONST EFI_PEI_SERVICES **PeiServices,
|
||||||
IN EFI_MEMORY_TYPE MemoryType,
|
IN EFI_MEMORY_TYPE MemoryType,
|
||||||
IN UINTN Pages,
|
IN UINTN Pages,
|
||||||
OUT EFI_PHYSICAL_ADDRESS *Memory
|
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,
|
PeiRegisterForShadow,
|
||||||
PeiFfsFindSectionData3,
|
PeiFfsFindSectionData3,
|
||||||
PeiFfsGetFileInfo2,
|
PeiFfsGetFileInfo2,
|
||||||
PeiResetSystem2
|
PeiResetSystem2,
|
||||||
|
PeiFreePages,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -231,6 +232,11 @@ PeiCore (
|
|||||||
HandoffInformationTable->EfiFreeMemoryTop = OldCoreData->FreePhysicalMemoryTop;
|
HandoffInformationTable->EfiFreeMemoryTop = OldCoreData->FreePhysicalMemoryTop;
|
||||||
HandoffInformationTable->EfiFreeMemoryBottom = HandoffInformationTable->EfiEndOfHobList + sizeof (EFI_HOB_GENERIC_HEADER);
|
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
|
// 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
|
@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.
|
and location of temporary RAM, the stack location and the BFV location.
|
||||||
@ -121,6 +121,20 @@ ConvertPpiPointers (
|
|||||||
|
|
||||||
for (Index = 0; Index < PcdGet32 (PcdPeiCoreMaxPpiSupported); Index++) {
|
for (Index = 0; Index < PcdGet32 (PcdPeiCoreMaxPpiSupported); Index++) {
|
||||||
if (Index < PrivateData->PpiData.PpiListEnd || Index > PrivateData->PpiData.NotifyListEnd) {
|
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
|
// Convert PPI pointer in old Heap
|
||||||
//
|
//
|
||||||
|
Loading…
x
Reference in New Issue
Block a user