/*++ | |
Copyright (c) 2006, 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 | |
http://opensource.org/licenses/bsd-license.php | |
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
Module Name: | |
Support.c | |
Abstract: | |
Revision History: | |
--*/ | |
#include "EfiLdr.h" | |
EFI_STATUS | |
EfiAddMemoryDescriptor( | |
UINTN *NoDesc, | |
EFI_MEMORY_DESCRIPTOR *Desc, | |
EFI_MEMORY_TYPE Type, | |
EFI_PHYSICAL_ADDRESS BaseAddress, | |
UINT64 NoPages, | |
UINT64 Attribute | |
) | |
{ | |
UINTN NumberOfDesc; | |
UINT64 Temp; | |
UINTN Index; | |
if (NoPages == 0) { | |
return EFI_SUCCESS; | |
} | |
// | |
// See if the new memory descriptor needs to be carved out of an existing memory descriptor | |
// | |
NumberOfDesc = *NoDesc; | |
for (Index = 0; Index < NumberOfDesc; Index++) { | |
if (Desc[Index].Type == EfiConventionalMemory) { | |
Temp = DivU64x32 ((BaseAddress - Desc[Index].PhysicalStart), EFI_PAGE_SIZE) + NoPages; | |
if ((Desc[Index].PhysicalStart < BaseAddress) && (Desc[Index].NumberOfPages >= Temp)) { | |
if (Desc[Index].NumberOfPages > Temp) { | |
Desc[*NoDesc].Type = EfiConventionalMemory; | |
Desc[*NoDesc].PhysicalStart = BaseAddress + MultU64x32 (NoPages, EFI_PAGE_SIZE); | |
Desc[*NoDesc].NumberOfPages = Desc[Index].NumberOfPages - Temp; | |
Desc[*NoDesc].VirtualStart = 0; | |
Desc[*NoDesc].Attribute = Desc[Index].Attribute; | |
*NoDesc = *NoDesc + 1; | |
} | |
Desc[Index].NumberOfPages = Temp - NoPages; | |
} | |
if ((Desc[Index].PhysicalStart == BaseAddress) && (Desc[Index].NumberOfPages == NoPages)) { | |
Desc[Index].Type = Type; | |
Desc[Index].Attribute = Attribute; | |
return EFI_SUCCESS; | |
} | |
if ((Desc[Index].PhysicalStart == BaseAddress) && (Desc[Index].NumberOfPages > NoPages)) { | |
Desc[Index].NumberOfPages -= NoPages; | |
Desc[Index].PhysicalStart += MultU64x32 (NoPages, EFI_PAGE_SIZE); | |
} | |
} | |
} | |
// | |
// Add the new memory descriptor | |
// | |
Desc[*NoDesc].Type = Type; | |
Desc[*NoDesc].PhysicalStart = BaseAddress; | |
Desc[*NoDesc].NumberOfPages = NoPages; | |
Desc[*NoDesc].VirtualStart = 0; | |
Desc[*NoDesc].Attribute = Attribute; | |
*NoDesc = *NoDesc + 1; | |
return EFI_SUCCESS; | |
} | |
UINTN | |
FindSpace ( | |
UINTN NoPages, | |
IN UINTN *NumberOfMemoryMapEntries, | |
IN EFI_MEMORY_DESCRIPTOR *EfiMemoryDescriptor, | |
EFI_MEMORY_TYPE Type, | |
UINT64 Attribute | |
) | |
{ | |
EFI_PHYSICAL_ADDRESS MaxPhysicalStart; | |
UINT64 MaxNoPages; | |
UINTN Index; | |
EFI_MEMORY_DESCRIPTOR *CurrentMemoryDescriptor; | |
MaxPhysicalStart = 0; | |
MaxNoPages = 0; | |
CurrentMemoryDescriptor = NULL; | |
for (Index = 0; Index < *NumberOfMemoryMapEntries; Index++) { | |
if (EfiMemoryDescriptor[Index].PhysicalStart + LShiftU64(EfiMemoryDescriptor[Index].NumberOfPages, EFI_PAGE_SHIFT) <= 0x100000) { | |
continue; | |
} | |
if ((EfiMemoryDescriptor[Index].Type == EfiConventionalMemory) && | |
(EfiMemoryDescriptor[Index].NumberOfPages >= NoPages)) { | |
if (EfiMemoryDescriptor[Index].PhysicalStart > MaxPhysicalStart) { | |
if (EfiMemoryDescriptor[Index].PhysicalStart + LShiftU64(EfiMemoryDescriptor[Index].NumberOfPages, EFI_PAGE_SHIFT) <= 0x100000000ULL) { | |
MaxPhysicalStart = EfiMemoryDescriptor[Index].PhysicalStart; | |
MaxNoPages = EfiMemoryDescriptor[Index].NumberOfPages; | |
CurrentMemoryDescriptor = &EfiMemoryDescriptor[Index]; | |
} | |
} | |
} | |
if ((EfiMemoryDescriptor[Index].Type == EfiReservedMemoryType) || | |
(EfiMemoryDescriptor[Index].Type >= EfiACPIReclaimMemory) ) { | |
continue; | |
} | |
if ((EfiMemoryDescriptor[Index].Type == EfiRuntimeServicesCode) || | |
(EfiMemoryDescriptor[Index].Type == EfiRuntimeServicesData)) { | |
break; | |
} | |
} | |
if (MaxPhysicalStart == 0) { | |
return 0; | |
} | |
if (MaxNoPages != NoPages) { | |
CurrentMemoryDescriptor->NumberOfPages = MaxNoPages - NoPages; | |
EfiMemoryDescriptor[*NumberOfMemoryMapEntries].Type = Type; | |
EfiMemoryDescriptor[*NumberOfMemoryMapEntries].PhysicalStart = MaxPhysicalStart + LShiftU64(MaxNoPages - NoPages, EFI_PAGE_SHIFT); | |
EfiMemoryDescriptor[*NumberOfMemoryMapEntries].NumberOfPages = NoPages; | |
EfiMemoryDescriptor[*NumberOfMemoryMapEntries].VirtualStart = 0; | |
EfiMemoryDescriptor[*NumberOfMemoryMapEntries].Attribute = Attribute; | |
*NumberOfMemoryMapEntries = *NumberOfMemoryMapEntries + 1; | |
} else { | |
CurrentMemoryDescriptor->Type = Type; | |
CurrentMemoryDescriptor->Attribute = Attribute; | |
} | |
return (UINTN)(MaxPhysicalStart + LShiftU64(MaxNoPages - NoPages, EFI_PAGE_SHIFT)); | |
} | |
VOID | |
GenMemoryMap ( | |
UINTN *NumberOfMemoryMapEntries, | |
EFI_MEMORY_DESCRIPTOR *EfiMemoryDescriptor, | |
BIOS_MEMORY_MAP *BiosMemoryMap | |
) | |
{ | |
UINT64 BaseAddress; | |
UINT64 Length; | |
EFI_MEMORY_TYPE Type; | |
UINTN Index; | |
UINTN Attr; | |
UINT64 Ceiling; | |
Ceiling = 0xFFFFFFFF; | |
for (Index = 0; Index < BiosMemoryMap->MemoryMapSize / sizeof(BIOS_MEMORY_MAP_ENTRY); Index++) { | |
switch (BiosMemoryMap->MemoryMapEntry[Index].Type) { | |
case (INT15_E820_AddressRangeMemory): | |
Type = EfiConventionalMemory; | |
Attr = EFI_MEMORY_WB; | |
break; | |
case (INT15_E820_AddressRangeReserved): | |
Type = EfiReservedMemoryType; | |
Attr = EFI_MEMORY_UC; | |
break; | |
case (INT15_E820_AddressRangeACPI): | |
Type = EfiACPIReclaimMemory; | |
Attr = EFI_MEMORY_WB; | |
break; | |
case (INT15_E820_AddressRangeNVS): | |
Type = EfiACPIMemoryNVS; | |
Attr = EFI_MEMORY_UC; | |
break; | |
default: | |
// We should not get here, according to ACPI 2.0 Spec. | |
// BIOS behaviour of the Int15h, E820h | |
Type = EfiReservedMemoryType; | |
Attr = EFI_MEMORY_UC; | |
break; | |
} | |
if (Type == EfiConventionalMemory) { | |
BaseAddress = BiosMemoryMap->MemoryMapEntry[Index].BaseAddress; | |
Length = BiosMemoryMap->MemoryMapEntry[Index].Length; | |
if (BaseAddress & EFI_PAGE_MASK) { | |
Length = Length + (BaseAddress & EFI_PAGE_MASK) - EFI_PAGE_SIZE; | |
BaseAddress = LShiftU64 (RShiftU64 (BaseAddress, EFI_PAGE_SHIFT) + 1, EFI_PAGE_SHIFT); | |
} | |
} else { | |
BaseAddress = BiosMemoryMap->MemoryMapEntry[Index].BaseAddress; | |
Length = BiosMemoryMap->MemoryMapEntry[Index].Length + (BaseAddress & EFI_PAGE_MASK); | |
BaseAddress = LShiftU64 (RShiftU64 (BaseAddress, EFI_PAGE_SHIFT), EFI_PAGE_SHIFT); | |
if (Length & EFI_PAGE_MASK) { | |
Length = LShiftU64 (RShiftU64 (Length, EFI_PAGE_SHIFT) + 1, EFI_PAGE_SHIFT); | |
} | |
// | |
// Update Memory Ceiling | |
// | |
if ((BaseAddress >= 0x100000) && (BaseAddress < 0x100000000ULL)) { | |
if (Ceiling > BaseAddress) { | |
Ceiling = BaseAddress; | |
} | |
} | |
} | |
EfiAddMemoryDescriptor ( | |
NumberOfMemoryMapEntries, | |
EfiMemoryDescriptor, | |
Type, | |
(EFI_PHYSICAL_ADDRESS)BaseAddress, | |
RShiftU64 (Length, EFI_PAGE_SHIFT), | |
Attr | |
); | |
} | |
// | |
// Update MemoryMap according to Ceiling | |
// | |
for (Index = 0; Index < *NumberOfMemoryMapEntries; Index++) { | |
if ((EfiMemoryDescriptor[Index].Type == EfiConventionalMemory) && | |
(EfiMemoryDescriptor[Index].PhysicalStart > 0x100000) && | |
(EfiMemoryDescriptor[Index].PhysicalStart < 0x100000000ULL)) { | |
if (EfiMemoryDescriptor[Index].PhysicalStart >= Ceiling) { | |
EfiMemoryDescriptor[Index].Type = EfiReservedMemoryType; | |
} | |
} | |
} | |
} |