gcd.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 2,443 行 · 第 1/5 页
C
2,443 行
UINT64
CoreConvertResourceDescriptorHobAttributesToCapabilities (
EFI_GCD_MEMORY_TYPE GcdMemoryType,
UINT64 Attributes
)
/*++
Routine Description:
Converts a Resource Descriptor HOB attributes mask to an EFI Memory Descriptor
capabilities mask
Arguments:
GcdMemoryType - Type of resource in the GCD memory map.
Attributes - The attribute mask in the Resource Descriptor HOB.
Returns:
The capabilities mask for an EFI Memory Descriptor.
--*/
{
UINT64 Capabilities;
GCD_ATTRIBUTE_CONVERSION_ENTRY *Conversion;
//
// Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
//
for (Capabilities = 0, Conversion = mAttributeConversionTable; Conversion->Attribute != 0; Conversion++) {
if (Conversion->Memory || (GcdMemoryType != EfiGcdMemoryTypeSystemMemory)) {
if (Attributes & Conversion->Attribute) {
Capabilities |= Conversion->Capability;
}
}
}
return Capabilities;
}
EFI_STATUS
CoreInitializeMemoryServices (
IN VOID **HobStart,
OUT EFI_PHYSICAL_ADDRESS *MemoryBaseAddress,
OUT UINT64 *MemoryLength
)
/*++
Routine Description:
External function. Initializes the GCD and memory services based on the memory
descriptor HOBs. This function is responsible for priming the GCD map and the
memory map, so memory allocations and resource allocations can be made. The first
part of this function can not depend on any memory services until at least one
memory descriptor is provided to the memory services. Then the memory services
can be used to intialize the GCD map.
Arguments:
HobStart - The start address of the HOB.
MemoryBaseAddress - Start address of memory region found to init DXE core.
MemoryLength - Length of memory region found to init DXE core.
Returns:
EFI_SUCCESS - Memory services successfully initialized.
--*/
{
EFI_STATUS Status;
EFI_PEI_HOB_POINTERS Hob;
EFI_MEMORY_TYPE_INFORMATION *EfiMemoryTypeInformation;
UINTN DataSize;
BOOLEAN Found;
EFI_HOB_HANDOFF_INFO_TABLE *PhitHob;
EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
EFI_HOB_RESOURCE_DESCRIPTOR *PhitResourceHob;
EFI_PHYSICAL_ADDRESS BaseAddress;
UINT64 Length;
UINT64 Attributes;
UINT64 Capabilities;
EFI_PHYSICAL_ADDRESS MaxMemoryBaseAddress;
UINT64 MaxMemoryLength;
UINT64 MaxMemoryAttributes;
EFI_PHYSICAL_ADDRESS MaxAddress;
EFI_PHYSICAL_ADDRESS HighAddress;
EFI_HOB_RESOURCE_DESCRIPTOR *MaxResourceHob;
//
// Point at the first HOB. This must be the PHIT HOB.
//
Hob.Raw = *HobStart;
ASSERT (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_HANDOFF);
//
// Initialize the spin locks and maps in the memory services.
// Also fill in the memory services into the EFI Boot Services Table
//
CoreInitializePool ();
//
// Initialize Local Variables
//
PhitResourceHob = NULL;
MaxResourceHob = NULL;
ResourceHob = NULL;
BaseAddress = 0;
Length = 0;
Attributes = 0;
MaxMemoryBaseAddress = 0;
MaxMemoryLength = 0;
MaxMemoryAttributes = 0;
//
// Cache the PHIT HOB for later use
//
PhitHob = Hob.HandoffInformationTable;
//
// See if a Memory Type Information HOB is available
//
Status = GetNextGuidHob (&Hob.Raw, &gEfiMemoryTypeInformationGuid, &EfiMemoryTypeInformation, &DataSize);
if (!EFI_ERROR (Status) &&
EfiMemoryTypeInformation != NULL &&
DataSize > 0 &&
DataSize <= (EfiMaxMemoryType + 1) * sizeof (EFI_MEMORY_TYPE_INFORMATION)) {
gBS->CopyMem (&gMemoryTypeInformation, EfiMemoryTypeInformation, DataSize);
}
//
// Find the Resource Descriptor HOB that contains range FreeMemoryBaseAddress..FreeMemoryLength
//
Length = 0;
Found = FALSE;
for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
ResourceHob = Hob.ResourceDescriptor;
if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&
(ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES ) {
if (PhitHob->EfiFreeMemoryBottom >= ResourceHob->PhysicalStart &&
PhitHob->EfiFreeMemoryTop <= (ResourceHob->PhysicalStart + ResourceHob->ResourceLength) ) {
//
// Cache the resource descriptor HOB for the memory region described by the PHIT HOB
//
PhitResourceHob = ResourceHob;
Found = TRUE;
Attributes = PhitResourceHob->ResourceAttribute;
BaseAddress = PageAlignAddress (PhitHob->EfiMemoryTop);
Length = PageAlignLength (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - BaseAddress);
if (Length < MINIMUM_INITIAL_MEMORY_SIZE) {
BaseAddress = PageAlignAddress (PhitHob->EfiFreeMemoryBottom);
Length = PageAlignLength (PhitHob->EfiFreeMemoryTop - BaseAddress);
if (Length < MINIMUM_INITIAL_MEMORY_SIZE) {
BaseAddress = PageAlignAddress (ResourceHob->PhysicalStart);
Length = PageAlignLength ((UINT64)*HobStart - BaseAddress);
}
}
break;
}
}
}
}
//
// Assert if a resource descriptor HOB for the memory region described by the PHIT was not found
//
ASSERT (Found);
//
// Search all the resource descriptor HOBs from the highest possible addresses down for a memory
// region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB.
// The max address must be within the physically addressible range for the processor.
//
MaxMemoryLength = 0;
MaxAddress = EFI_MAX_ADDRESS;
do {
HighAddress = 0;
Found = FALSE;
//
// Search for a tested memory region that is below MaxAddress
//
for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
//
// See if this is a resource descriptor HOB that does not contain the PHIT.
//
if (Hob.ResourceDescriptor != PhitResourceHob && GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
ResourceHob = Hob.ResourceDescriptor;
//
// See if this resource descrior HOB describes tested system memory below MaxAddress
//
if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&
(ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES &&
ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MaxAddress ) {
//
// See if this is the highest tested system memory region below MaxAddress
//
if (ResourceHob->PhysicalStart > HighAddress) {
MaxResourceHob = ResourceHob;
HighAddress = MaxResourceHob->PhysicalStart;
Found = TRUE;
}
}
}
}
if (Found) {
//
// Compute the size of the tested memory region below MaxAddrees
//
MaxMemoryBaseAddress = PageAlignAddress (MaxResourceHob->PhysicalStart);
MaxMemoryLength = PageAlignLength (MaxResourceHob->PhysicalStart + MaxResourceHob->ResourceLength - MaxMemoryBaseAddress);
MaxMemoryAttributes = MaxResourceHob->ResourceAttribute;
}
MaxAddress = ResourceHob->PhysicalStart;
} while (Found && MaxMemoryLength < MINIMUM_INITIAL_MEMORY_SIZE);
//
//
//
if ((Length < MINIMUM_INITIAL_MEMORY_SIZE) ||
(MaxMemoryBaseAddress > BaseAddress && MaxMemoryLength >= MINIMUM_INITIAL_MEMORY_SIZE) ) {
BaseAddress = MaxMemoryBaseAddress;
Length = MaxMemoryLength;
Attributes = MaxMemoryAttributes;
}
//
// If no memory regions are found that are big enough to initialize the DXE core, then ASSERT().
//
ASSERT (Length >= MINIMUM_INITIAL_MEMORY_SIZE);
//
// Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
//
Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory, Attributes);
//
// Declare the very first memory region, so the EFI Memory Services are available.
//
CoreAddMemoryDescriptor (
EfiConventionalMemory,
BaseAddress,
RShiftU64 (Length, EFI_PAGE_SHIFT),
Capabilities
);
*MemoryBaseAddress = BaseAddress;
*MemoryLength = Length;
return EFI_SUCCESS;
}
EFI_STATUS
CoreInitializeGcdServices (
IN VOID **HobStart,
IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress,
IN UINT64 MemoryLength
)
/*++
Routine Description:
External function. Initializes the GCD and memory services based on the memory
descriptor HOBs. This function is responsible for priming the GCD map and the
memory map, so memory allocations and resource allocations can be made. The first
part of this function can not depend on any memory services until at least one
memory descriptor is provided to the memory services. Then the memory services
can be used to intialize the GCD map.
Arguments:
HobStart - The start address of the HOB
MemoryBaseAddress - Start address of memory region found to init DXE core.
MemoryLength - Length of memory region found to init DXE core.
Returns:
EFI_SUCCESS - GCD services successfully initialized.
--*/
{
EFI_PEI_HOB_POINTERS Hob;
VOID *NewHobList;
EFI_HOB_HANDOFF_INFO_TABLE *PhitHob;
UINT8 SizeOfMemorySpace;
UINT8 SizeOfIoSpace;
EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
EFI_PHYSICAL_ADDRESS BaseAddress;
UINT64 Length;
EFI_STATUS Status;
EFI_GCD_MAP_ENTRY *Entry;
EFI_GCD_MEMORY_TYPE GcdMemoryType;
EFI_GCD_IO_TYPE GcdIoType;
EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;
EFI_HOB_MEMORY_ALLOCATION *MemoryHob;
EFI_HOB_FIRMWARE_VOLUME *FirmwareVolumeHob;
UINTN NumberOfDescriptors;
EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;
UINTN Index;
UINT64 Capabilities;
//
// Cache the PHIT HOB for later use
//
PhitHob = (EFI_HOB_HANDOFF_INFO_TABLE *)(*HobStart);
//
// Get the number of address lines in the I/O and Memory space for the CPU
//
Status = GetCpuHobInfo (*HobStart, &SizeOfMemorySpace, &SizeOfIoSpace);
ASSERT_EFI_ERROR (Status);
//
// Initialize the GCD Memory Space Map
//
Entry = CoreAllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdMemorySpaceMapEntryTemplate);
ASSERT (Entry != NULL);
Entry->EndAddress = LShiftU64 (1, SizeOfMemorySpace) - 1;
InsertHeadList (&mGcdMemorySpaceMap, &Entry->Link);
//
// Initialize the GCD I/O Space Map
//
Entry = CoreAllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdIoSpaceMapEntryTemplate);
ASSERT (Entry != NULL);
Entry->EndAddress = LShiftU64 (1, SizeOfIoSpace) - 1;
InsertHeadList (&mGcdIoSpaceMap, &Entry->Link);
//
// Walk the HOB list and add all resource descriptors to the GCD
//
for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
GcdMemoryType = EfiGcdMemoryTypeNonExistent;
GcdIoType = EfiGcdIoTypeNonExistent;
if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
ResourceHob = Hob.ResourceDescriptor;
switch (ResourceHob->ResourceType) {
case EFI_RESOURCE_SYSTEM_MEMORY:
if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES) {
GcdMemoryType = EfiGcdMemoryTypeSystemMemory;
}
if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == INITIALIZED_MEMORY_ATTRIBUTES) {
GcdMemoryType = EfiGcdMemoryTypeReserved;
}
if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == PRESENT_MEMORY_ATTRIBUTES) {
GcdMemoryType = EfiGcdMemoryTypeReserved;
}
break;
case EFI_RESOURCE_MEMORY_MAPPED_IO:
case EFI_RESOURCE_FIRMWARE_DEVICE:
GcdMemoryType = EfiGcdMemoryTypeMemoryMappedIo;
break;
case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT:
case EFI_RESOURCE_MEMORY_RESERVED:
GcdMemoryType = EfiGcdMemoryTypeReserved;
break;
case EFI_RESOURCE_IO:
GcdIoType = EfiGcdIoTypeIo;
break;
case EFI_RESOURCE_IO_RESERVED:
GcdIoType = EfiGcdIoTypeReserved;
break;
}
if (GcdMemoryType != EfiGcdMemoryTypeNonExistent) {
//
// Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
//
Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (
GcdMemoryType,
ResourceHob->ResourceAttribute
);
Status = CoreInternalAddMemorySpace (
GcdMemoryType,
ResourceHob->PhysicalStart,
ResourceHob->ResourceLength,
Capabilities
);
}
if (GcdIoType != EfiGcdIoTypeNonExistent) {
Status = CoreAddIoSpace (
GcdIoType,
ResourceHob->PhysicalStart,
ResourceHob->ResourceLength
);
}
}
}
//
// Allocate first memory region from the GCD by the DXE core
//
Status = CoreAllocateMemorySpace (
EfiGcdAllocateAddress,
EfiGcdMemoryTypeSystemMemory,
0,
MemoryLength,
&MemoryBaseAddress,
gDxeCoreImageHandle,
NULL
);
//
// Walk the HOB list and allocate all memory space that is consumed by memory allocation HOBs,
// and Firmware Volume HOBs. Also update the EFI Memory Map with the memory allocation HOBs.
//
for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
MemoryHob = Hob.MemoryAllocation;
BaseAddress = MemoryHob->AllocDescriptor.MemoryBaseAddress;
Status = CoreAllocateMemorySpace (
EfiGcdAllocateAddress,
EfiGcdMemoryTypeSystemMemory,
0,
MemoryHob->AllocDescriptor.MemoryLength,
&BaseAddress,
gDxeCoreImageHandle,
NULL
);
if (!EFI_ERROR (Status)) {
Status = CoreGetMemorySpaceDescriptor (MemoryHob->AllocDescriptor.MemoryBaseAddress, &Descriptor);
if (!EFI_ERROR (Status)) {
CoreAddMemoryDescriptor (
MemoryHob->AllocDescriptor.MemoryType,
MemoryHob->AllocDescriptor.MemoryBaseAddress,
RShiftU64 (MemoryHob->AllocDescriptor.MemoryLength, EFI_PAGE_SHIFT),
Descriptor.Capabilities & (~EFI_MEMORY_RUNTIME)
);
}
}
}
if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV) {
FirmwareVolumeHob = Hob.FirmwareVolume;
BaseAddress = FirmwareVolumeHob->BaseAddress;
Status = CoreAllocateMemorySpace (
EfiGcdAllocateAddress,
EfiGcdMemoryTypeMemoryMappedIo,
0,
FirmwareVolumeHob->Length,
&BaseAddress,
gDxeCoreImageHandle,
NULL
);
}
}
//
// Relocate HOB List to an allocated pool buffer.
//
NewHobList = CoreAllocateCopyPool (
(UINTN)PhitHob->EfiFreeMemoryBottom - (UINTN)(*HobStart),
*HobStart
);
ASSERT (NewHobList != NULL);
*HobStart = NewHobList;
//
// Add and allocate the remaining unallocated system memory to the memory services.
//
Status = CoreGetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);
for (Index = 0; Index < NumberOfDescri
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?