pcidevicesupport.c

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

C
1,352
字号
                  );

  if (EFI_ERROR (Status)) {
    return NULL;
  }

  EfiZeroMem (Dev, sizeof (PCI_IO_DEVICE));
  Dev->Signature  = PCI_IO_DEVICE_SIGNATURE;
  Dev->Handle     = RootBridgeHandle;
  InitializeListHead (&Dev->ChildList);

  Status = gBS->OpenProtocol (
                  RootBridgeHandle,
                  &gEfiDevicePathProtocolGuid,
                  (VOID **) &ParentDevicePath,
                  gPciBusDriverBinding.DriverBindingHandle,
                  RootBridgeHandle,
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
                  );

  if (EFI_ERROR (Status)) {
    gBS->FreePool (Dev);
    return NULL;
  }

  //
  // Record the root bridge parent device path
  //
  Dev->DevicePath = EfiDuplicateDevicePath (ParentDevicePath);

  //
  // Get the pci root bridge io protocol
  //
  Status = gBS->OpenProtocol (
                  RootBridgeHandle,
                  &gEfiPciRootBridgeIoProtocolGuid,
                  (VOID **) &PciRootBridgeIo,
                  gPciBusDriverBinding.DriverBindingHandle,
                  RootBridgeHandle,
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
                  );

  if (EFI_ERROR (Status)) {
    FreePciDevice (Dev);
    return NULL;
  }

  Dev->PciRootBridgeIo = PciRootBridgeIo;

  //
  // Initialize the PCI I/O instance structure
  //
  Status  = InitializePciIoInstance (Dev);
  Status  = InitializePciDriverOverrideInstance (Dev);

  //
  // Initialize reserved resource list and
  // option rom driver list
  //
  InitializeListHead (&Dev->ReservedResourceList);
  InitializeListHead (&Dev->OptionRomDriverList);

  return Dev;
}

PCI_IO_DEVICE *
GetRootBridgeByHandle (
  EFI_HANDLE RootBridgeHandle
  )
/*++

Routine Description:


Arguments:

  RootBridgeHandle    - An efi handle.

Returns:

  None

--*/
{
  PCI_IO_DEVICE   *RootBridgeDev;
  EFI_LIST_ENTRY  *CurrentLink;

  CurrentLink = gPciDevicePool.ForwardLink;

  while (CurrentLink && CurrentLink != &gPciDevicePool) {

    RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
    if (RootBridgeDev->Handle == RootBridgeHandle) {
      return RootBridgeDev;
    }

    CurrentLink = CurrentLink->ForwardLink;
  }

  return NULL;
}

BOOLEAN
RootBridgeExisted (
  IN EFI_HANDLE RootBridgeHandle
  )
/*++

Routine Description:

  This function searches if RootBridgeHandle has already existed
  in current device pool.

  If so, it means the given root bridge has been already enumerated.

Arguments:

  RootBridgeHandle   - An efi handle.

Returns:

  None

--*/
{
  PCI_IO_DEVICE *Bridge;

  Bridge = GetRootBridgeByHandle (RootBridgeHandle);

  if (Bridge != NULL) {
    return TRUE;
  }

  return FALSE;
}

BOOLEAN
PciDeviceExisted (
  IN PCI_IO_DEVICE    *Bridge,
  IN PCI_IO_DEVICE    *PciIoDevice
  )
/*++

Routine Description:
  
Arguments:

  Bridge       - A pointer to the PCI_IO_DEVICE.
  PciIoDevice  - A pointer to the PCI_IO_DEVICE.

Returns:

  None

--*/
{

  PCI_IO_DEVICE   *Temp;
  EFI_LIST_ENTRY  *CurrentLink;

  CurrentLink = Bridge->ChildList.ForwardLink;

  while (CurrentLink && CurrentLink != &Bridge->ChildList) {

    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);

    if (Temp == PciIoDevice) {
      return TRUE;
    }

    if (!IsListEmpty (&Temp->ChildList)) {
      if (PciDeviceExisted (Temp, PciIoDevice)) {
        return TRUE;
      }
    }

    CurrentLink = CurrentLink->ForwardLink;
  }

  return FALSE;
}

PCI_IO_DEVICE *
ActiveVGADeviceOnTheSameSegment (
  IN PCI_IO_DEVICE        *VgaDevice
  )
/*++

Routine Description:

Arguments:

  VgaDevice    - A pointer to the PCI_IO_DEVICE.
  
Returns:

  None

--*/
{
  EFI_LIST_ENTRY  *CurrentLink;
  PCI_IO_DEVICE   *Temp;

  CurrentLink = gPciDevicePool.ForwardLink;

  while (CurrentLink && CurrentLink != &gPciDevicePool) {

    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);

    if (Temp->PciRootBridgeIo->SegmentNumber == VgaDevice->PciRootBridgeIo->SegmentNumber) {

      Temp = ActiveVGADeviceOnTheRootBridge (Temp);

      if (Temp != NULL) {
        return Temp;
      }
    }

    CurrentLink = CurrentLink->ForwardLink;
  }

  return NULL;
}

PCI_IO_DEVICE *
ActiveVGADeviceOnTheRootBridge (
  IN PCI_IO_DEVICE        *RootBridge
  )
/*++

Routine Description:

Arguments:

  RootBridge    - A pointer to the PCI_IO_DEVICE.

Returns:

  None

--*/
{
  EFI_LIST_ENTRY  *CurrentLink;
  PCI_IO_DEVICE   *Temp;

  CurrentLink = RootBridge->ChildList.ForwardLink;

  while (CurrentLink && CurrentLink != &RootBridge->ChildList) {

    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);

    if (IS_PCI_VGA(&Temp->Pci) && 
        (Temp->Attributes &
         (EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY |
          EFI_PCI_IO_ATTRIBUTE_VGA_IO     |
          EFI_PCI_IO_ATTRIBUTE_VGA_IO_16))) {
      return Temp;
    }

    if (IS_PCI_BRIDGE (&Temp->Pci)) {

      Temp = ActiveVGADeviceOnTheRootBridge (Temp);

      if (Temp != NULL) {
        return Temp;
      }
    }

    CurrentLink = CurrentLink->ForwardLink;
  }

  return NULL;
}

EFI_STATUS
GetHpcPciAddress (
  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,
  IN  EFI_DEVICE_PATH_PROTOCOL         *HpcDevicePath,
  OUT UINT64                           *PciAddress
  )
/*++

Routine Description:

Arguments:

  PciRootBridgeIo       - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
  HpcDevicePath         - A pointer to the EFI_DEVICE_PATH_PROTOCL.
  PciAddress            - A pointer to the pci address.
  
Returns:

  None

--*/
// TODO:    EFI_NOT_FOUND - add return value to function comment
// TODO:    EFI_NOT_FOUND - add return value to function comment
// TODO:    EFI_SUCCESS - add return value to function comment
// TODO:    EFI_NOT_FOUND - add return value to function comment
{
  EFI_DEVICE_PATH_PROTOCOL  *CurrentDevicePath;
  EFI_DEV_PATH_PTR          Node;
  EFI_LIST_ENTRY            *CurrentLink;
  PCI_IO_DEVICE             *RootBridge;
  EFI_STATUS                Status;

  CurrentDevicePath = HpcDevicePath;

  //
  // Get the remaining device path for this PCI device, if it is a PCI device
  //
  while (!EfiIsDevicePathEnd (CurrentDevicePath)) {

    Node.DevPath = CurrentDevicePath;

    //
    // Check if it is PCI device Path?
    //
    if (Node.DevPath->Type != HARDWARE_DEVICE_PATH ||
        Node.DevPath->SubType != HW_PCI_DP         &&
        DevicePathNodeLength (Node.DevPath) != sizeof (PCI_DEVICE_PATH)) {
      CurrentDevicePath = EfiNextDevicePathNode (CurrentDevicePath);
      continue;
    }

    break;
  }

  //
  // Check if it is not PCI device path
  //
  if (EfiIsDevicePathEnd (CurrentDevicePath)) {
    return EFI_NOT_FOUND;
  }

  CurrentLink = gPciDevicePool.ForwardLink;

  while (CurrentLink && CurrentLink != &gPciDevicePool) {

    RootBridge = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
    //
    // Locate the right root bridge to start
    //
    if (RootBridge->PciRootBridgeIo == PciRootBridgeIo) {
      Status = GetHpcPciAddressFromRootBridge (
                RootBridge,
                CurrentDevicePath,
                PciAddress
                );
      if (EFI_ERROR (Status)) {
        return EFI_NOT_FOUND;
      }

      return EFI_SUCCESS;

    }

    CurrentLink = CurrentLink->ForwardLink;
  }

  return EFI_NOT_FOUND;
}

EFI_STATUS
GetHpcPciAddressFromRootBridge (
  IN  PCI_IO_DEVICE                    *RootBridge,
  IN  EFI_DEVICE_PATH_PROTOCOL         *RemainingDevicePath,
  OUT UINT64                           *PciAddress
  )
/*++

Routine Description:

Arguments:

  PciRootBridgeIo       - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
  HpcDevicePath         - A pointer to the EFI_DEVICE_PATH_PROTOCL.
  PciAddress            - A pointer to the pci address.

Returns:

  None

--*/
// TODO:    RootBridge - add argument and description to function comment
// TODO:    RemainingDevicePath - add argument and description to function comment
// TODO:    EFI_SUCCESS - add return value to function comment
// TODO:    EFI_NOT_FOUND - add return value to function comment
// TODO:    EFI_SUCCESS - add return value to function comment
{
  EFI_DEV_PATH_PTR          Node;
  PCI_IO_DEVICE             *Temp;
  EFI_DEVICE_PATH_PROTOCOL  *CurrentDevicePath;
  EFI_LIST_ENTRY            *CurrentLink;
  BOOLEAN                   MisMatch;

  MisMatch          = FALSE;

  CurrentDevicePath = RemainingDevicePath;
  Node.DevPath      = CurrentDevicePath;
  Temp              = NULL;

  while (!EfiIsDevicePathEnd (CurrentDevicePath)) {

    CurrentLink   = RootBridge->ChildList.ForwardLink;
    Node.DevPath  = CurrentDevicePath;

    while (CurrentLink && CurrentLink != &RootBridge->ChildList) {
      Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);

      if (Node.Pci->Device   == Temp->DeviceNumber &&
          Node.Pci->Function == Temp->FunctionNumber) {
        RootBridge = Temp;
        break;
      }

      CurrentLink = CurrentLink->ForwardLink;
    }

    //
    // Check if we find the bridge
    //
    if (CurrentLink == &RootBridge->ChildList) {

      MisMatch = TRUE;
      break;

    }

    CurrentDevicePath = EfiNextDevicePathNode (CurrentDevicePath);
  }

  if (MisMatch) {

    CurrentDevicePath = EfiNextDevicePathNode (CurrentDevicePath);

    if (EfiIsDevicePathEnd (CurrentDevicePath)) {
      *PciAddress = EFI_PCI_ADDRESS (RootBridge->BusNumber, Node.Pci->Device, Node.Pci->Function, 0);
      return EFI_SUCCESS;
    }

    return EFI_NOT_FOUND;
  }

  *PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);

  return EFI_SUCCESS;

}

⌨️ 快捷键说明

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