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 + -
显示快捷键?