page.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,579 行 · 第 1/3 页
C
1,579 行
Returns:
Status. On success, Memory is filled in with the base address allocated
EFI_INVALID_PARAMETER - Parameters violate checking rules defined in spec.
EFI_NOT_FOUND - Could not allocate pages match the requirement.
EFI_OUT_OF_RESOURCES - No enough pages to allocate.
EFI_SUCCESS - Pages successfully allocated.
--*/
{
EFI_STATUS Status;
UINT64 Start;
UINT64 MaxAddress;
UINTN Alignment;
if (Type < AllocateAnyPages || Type >= (UINTN) MaxAllocateType) {
return EFI_INVALID_PARAMETER;
}
if ((MemoryType >= EfiMaxMemoryType && MemoryType <= 0x7fffffff) ||
MemoryType == EfiConventionalMemory) {
return EFI_INVALID_PARAMETER;
}
Alignment = EFI_DEFAULT_PAGE_ALLOCATION_ALIGNMENT;
if (MemoryType == EfiACPIReclaimMemory ||
MemoryType == EfiACPIMemoryNVS ||
MemoryType == EfiRuntimeServicesCode ||
MemoryType == EfiRuntimeServicesData) {
Alignment = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT;
}
if (Type == AllocateAddress) {
if ((*Memory & (Alignment - 1)) != 0) {
return EFI_NOT_FOUND;
}
}
NumberOfPages += EFI_SIZE_TO_PAGES (Alignment) - 1;
NumberOfPages &= ~(EFI_SIZE_TO_PAGES (Alignment) - 1);
//
// If this is for below a particular address, then
//
Start = *Memory;
//
// The max address is the max natively addressable address for the processor
//
MaxAddress = EFI_MAX_ADDRESS;
if (Type == AllocateMaxAddress) {
MaxAddress = Start;
}
CoreAcquireMemoryLock ();
//
// If not a specific address, then find an address to allocate
//
if (Type != AllocateAddress) {
Start = FindFreePages (MaxAddress, NumberOfPages, MemoryType, Alignment);
if (Start == 0) {
Status = EFI_OUT_OF_RESOURCES;
goto Done;
}
}
//
// Convert pages from FreeMemory to the requested type
//
Status = CoreConvertPages (Start, NumberOfPages, MemoryType);
Done:
CoreReleaseMemoryLock ();
if (!EFI_ERROR (Status)) {
*Memory = Start;
}
return Status;
}
EFI_BOOTSERVICE
EFI_STATUS
EFIAPI
CoreFreePages (
IN EFI_PHYSICAL_ADDRESS Memory,
IN UINTN NumberOfPages
)
/*++
Routine Description:
Frees previous allocated pages.
Arguments:
Memory - Base address of memory being freed
NumberOfPages - The number of pages to free
Returns:
EFI_NOT_FOUND - Could not find the entry that covers the range
EFI_INVALID_PARAMETER - Address not aligned
EFI_SUCCESS -Pages successfully freed.
--*/
{
EFI_STATUS Status;
EFI_LIST_ENTRY *Link;
MEMORY_MAP *Entry;
UINTN Alignment;
//
// Free the range
//
CoreAcquireMemoryLock ();
//
// Find the entry that the covers the range
//
Entry = NULL;
for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
Entry = CR(Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
if (Entry->Start <= Memory && Entry->End > Memory) {
break;
}
}
if (Link == &gMemoryMap) {
CoreReleaseMemoryLock ();
return EFI_NOT_FOUND;
}
Alignment = EFI_DEFAULT_PAGE_ALLOCATION_ALIGNMENT;
if (Entry->Type == EfiACPIReclaimMemory ||
Entry->Type == EfiACPIMemoryNVS ||
Entry->Type == EfiRuntimeServicesCode ||
Entry->Type == EfiRuntimeServicesData) {
Alignment = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT;
}
if ((Memory & (Alignment - 1)) != 0) {
CoreReleaseMemoryLock ();
return EFI_INVALID_PARAMETER;
}
NumberOfPages += EFI_SIZE_TO_PAGES (Alignment) - 1;
NumberOfPages &= ~(EFI_SIZE_TO_PAGES (Alignment) - 1);
Status = CoreConvertPages (Memory, NumberOfPages, EfiConventionalMemory);
CoreReleaseMemoryLock ();
if (EFI_ERROR (Status)) {
return Status;
}
//
// Destroy the contents
//
if (Memory < EFI_MAX_ADDRESS) {
DEBUG_SET_MEMORY ((VOID *)(UINTN)Memory, NumberOfPages << EFI_PAGE_SHIFT);
}
return Status;
}
EFI_BOOTSERVICE
EFI_STATUS
EFIAPI
CoreGetMemoryMap (
IN OUT UINTN *MemoryMapSize,
IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
OUT UINTN *MapKey,
OUT UINTN *DescriptorSize,
OUT UINT32 *DescriptorVersion
)
/*++
Routine Description:
This function returns a copy of the current memory map. The map is an array of
memory descriptors, each of which describes a contiguous block of memory.
Arguments:
MemoryMapSize - A pointer to the size, in bytes, of the MemoryMap buffer. On
input, this is the size of the buffer allocated by the caller.
On output, it is the size of the buffer returned by the firmware
if the buffer was large enough, or the size of the buffer needed
to contain the map if the buffer was too small.
MemoryMap - A pointer to the buffer in which firmware places the current memory map.
MapKey - A pointer to the location in which firmware returns the key for the
current memory map.
DescriptorSize - A pointer to the location in which firmware returns the size, in
bytes, of an individual EFI_MEMORY_DESCRIPTOR.
DescriptorVersion - A pointer to the location in which firmware returns the version
number associated with the EFI_MEMORY_DESCRIPTOR.
Returns:
EFI_SUCCESS - The memory map was returned in the MemoryMap buffer.
EFI_BUFFER_TOO_SMALL - The MemoryMap buffer was too small. The current buffer size
needed to hold the memory map is returned in MemoryMapSize.
EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
--*/
{
EFI_STATUS Status;
UINTN Size;
UINTN BufferSize;
UINTN NumberOfRuntimeEntries;
EFI_LIST_ENTRY *Link;
MEMORY_MAP *Entry;
EFI_GCD_MAP_ENTRY *GcdMapEntry;
//
// Make sure the parameters are valid
//
if (MemoryMapSize == NULL) {
return EFI_INVALID_PARAMETER;
}
CoreAcquireGcdMemoryLock ();
//
// Count the number of Reserved and MMIO entries that are marked for runtime use
//
NumberOfRuntimeEntries = 0;
for (Link = mGcdMemorySpaceMap.ForwardLink; Link != &mGcdMemorySpaceMap; Link = Link->ForwardLink) {
GcdMapEntry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
if ((GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeReserved) ||
(GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo)) {
if ((GcdMapEntry->Attributes & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME) {
NumberOfRuntimeEntries++;
}
}
}
Size = sizeof (EFI_MEMORY_DESCRIPTOR);
//
// Make sure Size != sizeof(EFI_MEMORY_DESCRIPTOR). This will
// prevent people from having pointer math bugs in their code.
// now you have to use *DescriptorSize to make things work.
//
Size += sizeof(UINT64) - (Size % sizeof (UINT64));
if (DescriptorSize != NULL) {
*DescriptorSize = Size;
}
if (DescriptorVersion != NULL) {
*DescriptorVersion = EFI_MEMORY_DESCRIPTOR_VERSION;
}
CoreAcquireMemoryLock ();
//
// Compute the buffer size needed to fit the entire map
//
BufferSize = Size * NumberOfRuntimeEntries;
for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
BufferSize += Size;
}
if (*MemoryMapSize < BufferSize) {
Status = EFI_BUFFER_TOO_SMALL;
goto Done;
}
if (MemoryMap == NULL) {
Status = EFI_INVALID_PARAMETER;
goto Done;
}
//
// Build the map
//
EfiCommonLibZeroMem (MemoryMap, Size);
for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
ASSERT (Entry->VirtualStart == 0);
MemoryMap->Type = Entry->Type;
MemoryMap->PhysicalStart = Entry->Start;
MemoryMap->VirtualStart = Entry->VirtualStart;
MemoryMap->NumberOfPages = RShiftU64 (Entry->End - Entry->Start + 1, EFI_PAGE_SHIFT);
switch (Entry->Type) {
case EfiRuntimeServicesCode:
case EfiRuntimeServicesData:
case EfiPalCode:
MemoryMap->Attribute = Entry->Attribute | EFI_MEMORY_RUNTIME;
break;
default:
MemoryMap->Attribute = Entry->Attribute;
break;
}
MemoryMap = NextMemoryDescriptor (MemoryMap, Size);
}
for (Link = mGcdMemorySpaceMap.ForwardLink; Link != &mGcdMemorySpaceMap; Link = Link->ForwardLink) {
GcdMapEntry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
if ((GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeReserved) ||
(GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo)) {
if ((GcdMapEntry->Attributes & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME) {
MemoryMap->PhysicalStart = GcdMapEntry->BaseAddress;
MemoryMap->VirtualStart = 0;
MemoryMap->NumberOfPages = RShiftU64 ((GcdMapEntry->EndAddress - GcdMapEntry->BaseAddress + 1), EFI_PAGE_SHIFT);
MemoryMap->Attribute = GcdMapEntry->Attributes & ~EFI_MEMORY_PORT_IO;
if (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeReserved) {
MemoryMap->Type = EfiReservedMemoryType;
} else if (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) {
if ((GcdMapEntry->Attributes & EFI_MEMORY_PORT_IO) == EFI_MEMORY_PORT_IO) {
MemoryMap->Type = EfiMemoryMappedIOPortSpace;
} else {
MemoryMap->Type = EfiMemoryMappedIO;
}
}
MemoryMap = NextMemoryDescriptor (MemoryMap, Size);
}
}
}
Status = EFI_SUCCESS;
Done:
CoreReleaseMemoryLock ();
CoreReleaseGcdMemoryLock ();
//
// Update the map key finally
//
if (MapKey != NULL) {
*MapKey = mMemoryMapKey;
}
*MemoryMapSize = BufferSize;
return Status;
}
VOID *
CoreAllocatePoolPages (
IN EFI_MEMORY_TYPE PoolType,
IN UINTN NumberOfPages,
IN UINTN Alignment
)
/*++
Routine Description:
Internal function. Used by the pool functions to allocate pages
to back pool allocation requests.
Arguments:
PoolType - The type of memory for the new pool pages
NumberOfPages - No of pages to allocate
Alignment - Bits to align.
Returns:
The allocated memory, or NULL
--*/
{
EFI_STATUS Status;
UINT64 Start;
//
// Find the pages to convert
//
Start = FindFreePages (EFI_MAX_ADDRESS, NumberOfPages, PoolType, Alignment);
//
// Convert it to boot services data
//
if (Start == 0) {
DEBUG ((EFI_D_ERROR | EFI_D_PAGE, "AllocatePoolPages: failed to allocate %d pages\n", NumberOfPages));
} else {
Status = CoreConvertPages (Start, NumberOfPages, PoolType);
}
return (VOID *)(UINTN)Start;
}
VOID
CoreFreePoolPages (
IN EFI_PHYSICAL_ADDRESS Memory,
IN UINTN NumberOfPages
)
/*++
Routine Description:
Internal function. Frees pool pages allocated via AllocatePoolPages ()
Arguments:
Memory - The base address to free
NumberOfPages - The number of pages to free
Returns:
None
--*/
{
CoreConvertPages (Memory, NumberOfPages, EfiConventionalMemory);
}
EFI_STATUS
CoreTerminateMemoryMap (
IN UINTN MapKey
)
/*++
Routine Description:
Make sure the memory map is following all the construction rules,
it is the last time to check memory map error before exit boot services.
Arguments:
MapKey - Memory map key
Returns:
EFI_INVALID_PARAMETER - Memory map not consistent with construction rules.
EFI_SUCCESS - Valid memory map.
--*/
{
EFI_STATUS Status;
EFI_LIST_ENTRY *Link;
MEMORY_MAP *Entry;
Status = EFI_SUCCESS;
CoreAcquireMemoryLock ();
if (MapKey == mMemoryMapKey) {
//
// Make sure the memory map is following all the construction rules
// This is the last chance we will be able to display any messages on
// the console devices.
//
for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
Entry = CR(Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
if (Entry->Attribute & EFI_MEMORY_RUNTIME) {
if (Entry->Type == EfiACPIReclaimMemory || Entry->Type == EfiACPIMemoryNVS) {
DEBUG((EFI_D_ERROR, "ExitBootServices: ACPI memory entry has RUNTIME attribute set.\n"));
CoreReleaseMemoryLock ();
return EFI_INVALID_PARAMETER;
}
if (Entry->Start & (EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT - 1)) {
DEBUG((EFI_D_ERROR, "ExitBootServices: A RUNTIME memory entry is not on a proper alignment.\n"));
CoreReleaseMemoryLock ();
return EFI_INVALID_PARAMETER;
}
if ((Entry->End + 1) & (EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT - 1)) {
DEBUG((EFI_D_ERROR, "ExitBootServices: A RUNTIME memory entry is not on a proper alignment.\n"));
CoreReleaseMemoryLock ();
return EFI_INVALID_PARAMETER;
}
}
}
//
// The map key they gave us matches what we expect. Fall through and
// return success. In an ideal world we would clear out all of
// EfiBootServicesCode and EfiBootServicesData. However this function
// is not the last one called by ExitBootServices(), so we have to
// preserve the memory contents.
//
} else {
Status = EFI_INVALID_PARAMETER;
}
CoreReleaseMemoryLock ();
return Status;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?