pcienumerator.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 2,178 行 · 第 1/4 页

C
2,178
字号
  UINT64          TempOptionRomSize;

  MaxOptionRomSize = 0;

  //
  // Go through bridges to reach all devices
  //
  CurrentLink = Bridge->ChildList.ForwardLink;
  while (CurrentLink && CurrentLink != &Bridge->ChildList) {
    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
    if (!IsListEmpty (&Temp->ChildList)) {
      
      //
      // Get max option rom size under this bridge
      //
      TempOptionRomSize = GetMaxOptionRomSize (Temp);

      //
      // Compare with the option rom size of the bridge
      // Get the larger one
      //
      if (Temp->RomSize > TempOptionRomSize) {
        TempOptionRomSize = Temp->RomSize;
      }

    } else {
      
      //
      // For devices get the rom size directly
      //
      TempOptionRomSize = Temp->RomSize;
    }
    
    //
    // Get the largest rom size on this bridge
    //
    if (TempOptionRomSize > MaxOptionRomSize) {
      MaxOptionRomSize = TempOptionRomSize;
    }

    CurrentLink = CurrentLink->ForwardLink;
  }

  return MaxOptionRomSize;
}

EFI_STATUS
PciHostBridgeDeviceAttribute (
  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
  )
/*++

Routine Description:
  
    Process attributes of devices on this host bridge

Arguments:

Returns:

  None

--*/
// TODO:    PciResAlloc - add argument and description to function comment
// TODO:    EFI_NOT_FOUND - add return value to function comment
// TODO:    EFI_SUCCESS - add return value to function comment
{
  EFI_HANDLE    RootBridgeHandle;
  PCI_IO_DEVICE *RootBridgeDev;
  EFI_STATUS    Status;

  RootBridgeHandle = NULL;

  while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {

    //
    // Get RootBridg Device by handle
    //
    RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);

    if (RootBridgeDev == NULL) {
      return EFI_NOT_FOUND;
    }

    //
    // Set the attributes for devcies behind the Root Bridge
    //
    Status = DetermineDeviceAttribute (RootBridgeDev);
    if (EFI_ERROR (Status)) {
      return Status;
    }

  }

  return EFI_SUCCESS;
}

EFI_STATUS
GetResourceAllocationStatus (
  VOID        *AcpiConfig,
  OUT UINT64  *IoResStatus,
  OUT UINT64  *Mem32ResStatus,
  OUT UINT64  *PMem32ResStatus,
  OUT UINT64  *Mem64ResStatus,
  OUT UINT64  *PMem64ResStatus
  )
/*++

Routine Description:
  
    Get resource allocation status from the ACPI pointer

Arguments:

Returns:

  None

--*/
// TODO:    AcpiConfig - add argument and description to function comment
// TODO:    IoResStatus - add argument and description to function comment
// TODO:    Mem32ResStatus - add argument and description to function comment
// TODO:    PMem32ResStatus - add argument and description to function comment
// TODO:    Mem64ResStatus - add argument and description to function comment
// TODO:    PMem64ResStatus - add argument and description to function comment
// TODO:    EFI_SUCCESS - add return value to function comment
{

  UINT8                             *Temp;
  UINT64                            ResStatus;
  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ptr;

  Temp = (UINT8 *) AcpiConfig;

  while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {

    ptr       = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
    ResStatus = ptr->AddrTranslationOffset;

    switch (ptr->ResType) {
    case 0:
      if (ptr->AddrSpaceGranularity == 32) {
        if (ptr->SpecificFlag == 0x06) {
          //
          // Pmem32
          //
          *PMem32ResStatus = ResStatus;
        } else {
          //
          // Mem32
          //
          *Mem32ResStatus = ResStatus;
        }
      }

      if (ptr->AddrSpaceGranularity == 64) {
        if (ptr->SpecificFlag == 0x06) {
          //
          // PMem64
          //
          *PMem64ResStatus = ResStatus;
        } else {
          //
          // Mem64
          //
          *Mem64ResStatus = ResStatus;
        }
      }

      break;

    case 1:
      //
      // Io
      //
      *IoResStatus = ResStatus;
      break;

    default:
      break;
    }

    Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
  }

  return EFI_SUCCESS;
}

EFI_STATUS
RejectPciDevice (
  IN PCI_IO_DEVICE       *PciDevice
  )
/*++

Routine Description:
  
    Remove a PCI device from device pool and mark its bar

Arguments:

Returns:

  None

--*/
// TODO:    PciDevice - add argument and description to function comment
// TODO:    EFI_SUCCESS - add return value to function comment
// TODO:    EFI_ABORTED - add return value to function comment
// TODO:    EFI_SUCCESS - add return value to function comment
// TODO:    EFI_ABORTED - add return value to function comment
{
  PCI_IO_DEVICE   *Bridge;
  PCI_IO_DEVICE   *Temp;
  EFI_LIST_ENTRY  *CurrentLink;

  //
  // Remove the padding resource from a bridge
  //
  if ( IS_PCI_BRIDGE(&PciDevice->Pci) && \
       PciDevice->ResourcePaddingDescriptors ) {
    gBS->FreePool (PciDevice->ResourcePaddingDescriptors);
    PciDevice->ResourcePaddingDescriptors = NULL;
    return EFI_SUCCESS;
  }

  //
  // Skip RB and PPB
  //
  if (IS_PCI_BRIDGE (&PciDevice->Pci) || (!PciDevice->Parent)) {
    return EFI_ABORTED;
  }

  if (IS_CARDBUS_BRIDGE (&PciDevice->Pci)) {
    //
    // Get the root bridge device
    //
    Bridge = PciDevice;
    while (Bridge->Parent) {
      Bridge = Bridge->Parent;
    }

    RemoveAllPciDeviceOnBridge (Bridge->Handle, PciDevice);

    //
    // Mark its bar
    //
    InitializeP2C (PciDevice);
  }
    
  //
  // Remove the device
  //
  Bridge      = PciDevice->Parent;
  CurrentLink = Bridge->ChildList.ForwardLink;
  while (CurrentLink && CurrentLink != &Bridge->ChildList) {
    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
    if (Temp == PciDevice) {
      InitializePciDevice (Temp);
      RemoveEntryList (CurrentLink);
      FreePciDevice (Temp);
      return EFI_SUCCESS;
    }

    CurrentLink = CurrentLink->ForwardLink;
  }

  return EFI_ABORTED;
}

BOOLEAN
IsRejectiveDevice (
  IN  PCI_RESOURCE_NODE   *PciResNode
  )
/*++

Routine Description:
  
    Determine whethter a PCI device can be rejected

Arguments:

Returns:

  None

--*/
// TODO:    PciResNode - add argument and description to function comment
{
  PCI_IO_DEVICE *Temp;

  Temp = PciResNode->PciDev;

  //
  // Ensure the device is present
  //
  if (!Temp) {
    return FALSE;
  }
    
  //
  // PPB and RB should go ahead
  //
  if (IS_PCI_BRIDGE (&Temp->Pci) || (!Temp->Parent)) {
    return TRUE;
  }

  //
  // Skip device on Bus0
  //
  if ((Temp->Parent) && (Temp->BusNumber == 0)) {
    return FALSE;
  }
  
  //
  // Skip VGA
  //
  if (IS_PCI_VGA (&Temp->Pci)) {
    return FALSE;
  }

  return TRUE;
}

PCI_RESOURCE_NODE *
GetLargerConsumerDevice (
  IN  PCI_RESOURCE_NODE   *PciResNode1,
  IN  PCI_RESOURCE_NODE   *PciResNode2
  )
/*++

Routine Description:
  
    Get the larger resource consumer

Arguments:

Returns:

  None

--*/
// TODO:    PciResNode1 - add argument and description to function comment
// TODO:    PciResNode2 - add argument and description to function comment
{
  if (!PciResNode2) {
    return PciResNode1;
  }

  if ((IS_PCI_BRIDGE(&(PciResNode2->PciDev->Pci)) || !(PciResNode2->PciDev->Parent)) \
       && (PciResNode2->ResourceUsage != PciResUsagePadding) )
  {
    return PciResNode1;
  }

  if (!PciResNode1) {
    return PciResNode2;
  }

  if ((PciResNode1->Length) > (PciResNode2->Length)) {
    return PciResNode1;
  }

  return PciResNode2;

}

PCI_RESOURCE_NODE *
GetMaxResourceConsumerDevice (
  IN  PCI_RESOURCE_NODE   *ResPool
  )
/*++

Routine Description:
  
    Get the max resource consumer in the host resource pool 

Arguments:

Returns:

  None

--*/
// TODO:    ResPool - add argument and description to function comment
{
  PCI_RESOURCE_NODE *Temp;
  EFI_LIST_ENTRY    *CurrentLink;
  PCI_RESOURCE_NODE *PciResNode;
  PCI_RESOURCE_NODE *PPBResNode;

  PciResNode  = NULL;

  CurrentLink = ResPool->ChildList.ForwardLink;
  while (CurrentLink && CurrentLink != &ResPool->ChildList) {

    Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);

    if (!IsRejectiveDevice (Temp)) {
      CurrentLink = CurrentLink->ForwardLink;
      continue;
    }

    if ((IS_PCI_BRIDGE (&(Temp->PciDev->Pci)) || (!Temp->PciDev->Parent)) \
          && (Temp->ResourceUsage != PciResUsagePadding))
    {
      PPBResNode  = GetMaxResourceConsumerDevice (Temp);
      PciResNode  = GetLargerConsumerDevice (PciResNode, PPBResNode);
    } else {
      PciResNode = GetLargerConsumerDevice (PciResNode, Temp);
    }

    CurrentLink = CurrentLink->ForwardLink;
  }

  return PciResNode;
}

EFI_STATUS
PciHostBridgeAdjustAllocation (
  IN  PCI_RESOURCE_NODE   *IoPool,
  IN  PCI_RESOURCE_NODE   *Mem32Pool,
  IN  PCI_RESOURCE_NODE   *PMem32Pool,
  IN  PCI_RESOURCE_NODE   *Mem64Pool,
  IN  PCI_RESOURCE_NODE   *PMem64Pool,
  IN  UINT64              IoResStatus,
  IN  UINT64              Mem32ResStatus,
  IN  UINT64              PMem32ResStatus,
  IN  UINT64              Mem64ResStatus,
  IN  UINT64              PMem64ResStatus
  )
/*++

Routine Description:
  
    Adjust host bridge allocation so as to reduce resource requirement

Arguments:

Returns:

  None

--*/
// TODO:    IoPool - add argument and description to function comment
// TODO:    Mem32Pool - add argument and description to function comment
// TODO:    PMem32Pool - add argument and description to function comment
// TODO:    Mem64Pool - add argument and description to function comment
// TODO:    PMem64Pool - add argument and description to function comment
// TODO:    IoResStatus - add argument and description to function comment
// TODO:    Mem32ResStatus - add argument and description to function comment
// TODO:    PMem32ResStatus - add argument and description to function comment
// TODO:    Mem64ResStatus - add argument and description to function comment
// TODO:    PMem64ResStatus - add argument and description to function comment
// TODO:    EFI_ABORTED - add return value to function comment
// TODO:    EFI_SUCCESS - add return value to function comment
// TODO:    EFI_ABORTED - add return value to function comment
{
  BOOLEAN                               AllocationAjusted;
  PCI_RESOURCE_NODE                     *PciResNode;
  PCI_RESOURCE_NODE                     *ResPool[5];
  PCI_IO_DEVICE                         *RemovedPciDev[5];
  UINT64                                ResStatus[5];
  UINTN                                 RemovedPciDevNum;
  UINTN                                 DevIndex;
  UINTN                                 ResType;
  EFI_STATUS                            Status;
  EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA AllocFailExtendedData;

  PciResNode = NULL;
  EfiZeroMem (RemovedPciDev, 5 * sizeof (PCI_IO_DEVICE *));
  RemovedPciDevNum  = 0;

  ResPool[0]        = IoPool;
  ResPool[1]        = Mem32Pool;
  ResPool[2]        = PMem32Pool;
  ResPool[3]        = Mem64Pool;
  ResPool[4]        = PMem64Pool;

  ResStatus[0]      = IoResStatus;
  ResStatus[1]      = Mem32ResStatus;
  ResStatus[2]      = PMem32ResStatus;
  ResStatus[3]      = Mem64ResStatus;
  ResStatus[4]      = PMem64ResStatus;

  AllocationAjusted = FALSE;

  for (ResType = 0; ResType < 5; ResType++) {

    if (ResStatus[ResType] == EFI_RESOURCE_SATISFIED) {
      continue;
    }

    if (ResStatus[ResType] == EFI_RESOURCE_NONEXISTENT) {
      //
      // Hostbridge hasn't this resource type
      //
      return EFI_ABORTED;
    }
    
    //
    // Hostbridge hasn't enough resource
    //
    PciResNode = GetMaxResourceConsumerDevice (ResPool[ResType]);
    if (!PciResNode) {
      continue;
    }
    
    //
    // Check if the device has been removed before
    //
    for (DevIndex = 0; DevIndex < RemovedPciDevNum; DevIndex++) {
      if (PciResNode->PciDev == RemovedPciDev[DevIndex]) {
        continue;
      }
    }
    
    //
    // Remove the device if it isn't in the array
    //
    Status = RejectPciDevice (PciResNode->PciDev);
    if (Status == EFI_SUCCESS) {
      
      //
      // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
      //
      AllocFailExtendedData.DataHeader.HeaderSize = sizeof (EFI_STATUS_CODE_DATA);
      AllocFailExtendedData.DataHeader.Size = sizeof (EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA) -
      sizeof (EFI_STATUS_CODE_DATA);

      EfiCommonLibCopyMem (
        &AllocFailExtendedData.DataHeader.Type,
        &gEfiStatusCodeSpecificDataGuid,
        sizeof (EFI_GUID)
        );

      //
      // Have no way to get ReqRes, AllocRes & Bar here
      //
      AllocFailExtendedData.DevicePath  = PciResNode->PciDev->DevicePath;
      AllocFailExtendedData.Bar         = PciResNode->Bar;
      AllocFailExtendedData.ReqRes      = NULL;
      AllocFailExtendedData.AllocRes    = NULL;

      EfiLibReportStatusCode (
        EFI_PROGRESS_CODE,

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?