📄 page.c
字号:
Alignment = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT;
}
if (Type == AllocateAddress) {
if ((*Memory & (Alignment - 1)) != 0) {
return EFI_INVALID_PARAMETER;
}
}
NoPages += EFI_SIZE_TO_PAGES (Alignment) - 1;
NoPages &= ~(EFI_SIZE_TO_PAGES (Alignment) - 1);
//
// If this is for below a particular address, then
//
Start = *Memory;
MaxAddress = MAX_ADDRESS;
if (Type == AllocateMaxAddress) {
MaxAddress = Start;
}
AcquireLock (&MemoryLock);
//
// If not a specific address, then find an address to allocate
//
if (Type != AllocateAddress) {
Start = FindFreePages(MaxAddress, NoPages, MemoryType, Alignment);
if (!Start) {
Status = EFI_OUT_OF_RESOURCES;
goto Done;
}
}
//
// Convert pages from FreeMemory to the requested type
//
Status = ConvertPages (FALSE, Start, NoPages, MemoryType);
Done:
ReleaseLock (&MemoryLock);
if (!EFI_ERROR(Status)) {
*Memory = Start;
}
return Status;
}
EFI_STATUS
BOOTSERVICE
FreePages (
IN EFI_PHYSICAL_ADDRESS Memory,
IN UINTN NoPages
)
/*++
Routine Description:
Frees previous allocated pages.
Arguments:
Memory - Base address of memory being freed
NoPages - The number of pages to free
Returns:
Status.
--*/
{
EFI_STATUS Status;
LIST_ENTRY *Link;
MEMORY_MAP *Entry;
UINTN Alignment;
if (EfiAtRuntime) {
return EFI_UNSUPPORTED;
}
//
// Free the range
//
AcquireLock (&MemoryLock);
//
// Find the entry that the covers the range
//
for (Link = MemoryMap.Flink; Link != &MemoryMap; Link = Link->Flink) {
Entry = CR(Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
if (Entry->Start <= Memory && Entry->End > Memory) {
break;
}
}
if (Link == &MemoryMap) {
ReleaseLock (&MemoryLock);
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) {
ReleaseLock (&MemoryLock);
return EFI_INVALID_PARAMETER;
}
NoPages += EFI_SIZE_TO_PAGES (Alignment) - 1;
NoPages &= ~(EFI_SIZE_TO_PAGES (Alignment) - 1);
//
//check if the NoPages is valid
//
if(!NoPages || NoPages > RShiftU64(Entry->End - Entry->Start + 1, EFI_PAGE_SHIFT)){
ReleaseLock(&MemoryLock);
return EFI_INVALID_PARAMETER;
}
Status = ConvertPages (FALSE, Memory, NoPages, EfiConventionalMemory);
ReleaseLock (&MemoryLock);
if (EFI_ERROR(Status)) {
return Status;
}
//
// Destroy the contents
//
if (Memory < MAX_ADDRESS) {
DBGSETMEM ((VOID *) Memory, NoPages << EFI_PAGE_SHIFT);
}
return Status;
}
EFI_STATUS
BOOTSERVICE
GetMemoryMap (
IN OUT UINTN *MemoryMapSize,
IN OUT EFI_MEMORY_DESCRIPTOR *Desc,
OUT UINTN *MapKey,
OUT UINTN *DescriptorSize,
OUT UINT32 *DescriptorVersion
)
/*++
Routine Description:
Returns the current memory map.
Arguments:
MemoryMapSize - On input the sizeof of Desc
On output the amount of data return in Desc
Desc - The buffer to return the memory map in
MapKey - The address to return the current mapkey in
Returns:
Status.
On success, Desc & MemoryMapSize is completed with the current memory map.
On buffer too small, MemoryMapSize is completed with the buffer size needed.
--*/
{
UINTN BufferSize;
EFI_STATUS Status;
LIST_ENTRY *Link;
MEMORY_MAP *Entry;
UINTN Size;
if (MemoryMapSize == NULL) {
return EFI_INVALID_PARAMETER;
}
Size = sizeof(EFI_MEMORY_DESCRIPTOR);
//
// Make sure Size != sizeof(EFI_MEMORY_DESCRIPTOR). This will
// prevent people from having pointer math bugs in thier 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;
}
AcquireLock (&MemoryLock);
//
// Compute the buffer size needed to fit the entire map
//
BufferSize = 0;
for (Link = MemoryMap.Flink; Link != &MemoryMap; Link = Link->Flink) {
BufferSize += Size;
}
if (*MemoryMapSize < BufferSize) {
Status = EFI_BUFFER_TOO_SMALL;
goto Done;
}
if (Desc == NULL) {
Status = EFI_INVALID_PARAMETER;
goto Done;
}
//
// Build the map
//
ZeroMem (Desc, Size);
for (Link = MemoryMap.Flink; Link != &MemoryMap; Link = Link->Flink) {
Entry = CR(Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
ASSERT (!Entry->VirtualStart);
Desc->Type = Entry->Type;
Desc->PhysicalStart = Entry->Start;
Desc->VirtualStart = Entry->VirtualStart;
Desc->NumberOfPages = RShiftU64(Entry->End - Entry->Start + 1, EFI_PAGE_SHIFT);
switch (Entry->Type) {
case EfiReservedMemoryType:
case EfiUnusableMemory:
case EfiACPIReclaimMemory:
case EfiACPIMemoryNVS:
case EfiMemoryMappedIO:
case EfiMemoryMappedIOPortSpace:
case EfiLoaderCode:
case EfiLoaderData:
case EfiBootServicesCode:
case EfiBootServicesData:
case EfiConventionalMemory:
Desc->Attribute = Entry->Attribute;
break;
case EfiRuntimeServicesCode:
case EfiRuntimeServicesData:
case EfiPalCode:
Desc->Attribute = Entry->Attribute | EFI_MEMORY_RUNTIME;
break;
default:
Desc->Attribute = Entry->Attribute;
break;
}
Desc = NextMemoryDescriptor(Desc, Size);
}
//
//
//
if (MapKey) {
*MapKey = MemoryMapKey;
}
Status = EFI_SUCCESS;
Done:
ReleaseLock (&MemoryLock);
*MemoryMapSize = BufferSize;
return Status;
}
INTERNAL
VOID *
AllocatePoolPages (
IN EFI_MEMORY_TYPE PoolType,
IN UINTN NoPages,
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
NoPages - No of pages to allocate
Returns:
The allocated memory, or NULL.
--*/
{
UINT64 Start;
EFI_STATUS Status;
ASSERT (!EfiAtRuntime);
//
// Find the pages to convert
//
Start = FindFreePages (MAX_ADDRESS, NoPages, PoolType, Alignment);
//
// Convert it to boot services data
//
if (Start) {
Status = ConvertPages (FALSE, Start, NoPages, PoolType);
if (EFI_ERROR(Status)) {
Start = 0;
}
}
if (!Start) {
DEBUG((D_ERROR, "AllocatePoolPages: failed to allocate %d pages\n", NoPages));
}
return (VOID *) Start;
}
INTERNAL
VOID
FreePoolPages (
IN EFI_PHYSICAL_ADDRESS Memory,
IN UINTN NoPages
)
/*++
Routine Description:
Internal function. Frees pool pages allocated via AllocatePoolPages()
Arguments:
Memory - The base address to free
NoPages - The number of pages to free
Returns:
None
--*/
{
ConvertPages (FALSE, Memory, NoPages, EfiConventionalMemory);
}
EFI_STATUS
SetCodeSection (
IN EFI_PHYSICAL_ADDRESS Base,
IN UINTN NoPages,
IN EFI_MEMORY_TYPE MemoryType
)
// Used by the loader to set sections to code
/*++
Routine Description:
Used by the loader to convert code pages to code memory
types after any fixups have been applied
Arguments:
Base - The base address to change the type of
NoPages - The number of pages to change the type of
MemoryType - The new memory type for the range
Returns:
Status
--*/
{
EFI_STATUS Status;
AcquireLock (&MemoryLock);
Status = ConvertPages (TRUE, Base, NoPages, MemoryType);
ReleaseLock (&MemoryLock);
return Status;
}
EFI_STATUS
TerminateMemoryMap (
IN UINTN MapKey
)
{
EFI_STATUS Status;
LIST_ENTRY *Link;
MEMORY_MAP *Entry;
Status = EFI_SUCCESS;
AcquireLock (&MemoryLock);
if (MapKey == MemoryMapKey) {
//
// 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 = MemoryMap.Flink; Link != &MemoryMap; Link = Link->Flink) {
Entry = CR(Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
if (Entry->Attribute & EFI_MEMORY_RUNTIME) {
if (Entry->Type == EfiACPIReclaimMemory || Entry->Type == EfiACPIMemoryNVS) {
DEBUG((D_ERROR, "ExitBootServices: ACPI memory entry has RUNTIME attribute set.\n"));
ReleaseLock (&MemoryLock);
return EFI_INVALID_PARAMETER;
}
if (Entry->Start & (EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT - 1)) {
DEBUG((D_ERROR, "ExitBootServices: A RUNTIME memory entry is not on a proper alignment.\n"));
ReleaseLock (&MemoryLock);
return EFI_INVALID_PARAMETER;
}
if ((Entry->End + 1) & (EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT - 1)) {
DEBUG((D_ERROR, "ExitBootServices: A RUNTIME memory entry is not on a proper alignment.\n"));
ReleaseLock (&MemoryLock);
return EFI_INVALID_PARAMETER;
}
}
}
//
// No going back now. Lock memory map from changing
//
EfiAtRuntime = TRUE;
//
// 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;
}
ReleaseLock (&MemoryLock);
return Status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -