举例分析CoreConnectController 的Recursive 参数

ConnectController() Recurive 举例分析
Recursive 是一个重要参数, BIOS 对开机时间在是非常在意的,如果每个controller 都以 Recursive 带TRUE, 
那就会非常耗时。
EFI_STATUS
(EFIAPI *EFI_CONNECT_CONTROLLER)(
  IN  EFI_HANDLE                    ControllerHandle,
  IN  EFI_HANDLE                    *DriverImageHandle,   OPTIONAL
  IN  EFI_DEVICE_PATH_PROTOCOL      *RemainingDevicePath, OPTIONAL
  IN  BOOLEAN                       Recursive
  );


如果要在硬盘上读到内容,以下是协议栈,

FAT                 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
DiskIoDxe           EFI_DISK_IO_PROTOCOL
PartitionDxe        EFI_BLOCK_IO_PROTOCOL
DiskIoDxe           EFI_DISK_IO_PROTOCOL
AhciBusDxe          EFI_BLOCK_IO_PROTOCOL
AtaAtaPassThruDxe   EFI_ATA_PASS_THRU_PROTOCOL
SataController      EFI_IDE_CONTROLLER_INIT_PROTOCOL
PciBusDxe           EFI_PCI_IO_PROTOCOL
PciHostBridgeDxe    EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL

connect 其实在connect controller, 以上面为例,如果recursive 带TRUE, 那就会把下面的节点都connect 起来。

 

TRUE 
ConnectController() is called recursively until the entire tree of 
controllers below the controller specified by ControllerHandle have been created.

FALSE
The tree of controllers is only expanded one level.

看的具体实现:

    //
    // Fill in a handle buffer with ControllerHandle's children
    //
    for (Link = Handle->Protocols.ForwardLink, ChildHandleCount = 0; Link != &Handle->Protocols; Link = Link->ForwardLink) {
      Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
      for (ProtLink = Prot->OpenList.ForwardLink;
          ProtLink != &Prot->OpenList;
          ProtLink = ProtLink->ForwardLink) {
        OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
        if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
          ChildHandleBuffer[ChildHandleCount] = OpenData->ControllerHandle;
          ChildHandleCount++;
        }
      }
    }

    //
    // Release the protocol lock on the handle database
    //
    CoreReleaseProtocolLock ();

    //
    // Recursively connect each child handle
    //
    for (Index = 0; Index < ChildHandleCount; Index++) {
      CoreConnectController (
        ChildHandleBuffer[Index],
        NULL,
        NULL,
        TRUE
        );
    }

 Recursively connect each child handle

递归 即 传进来的参数 和函数里面调用的都是ControllerHandle

 

下面举两个例子,以次为TRUE和 FALSE

ConnectAllUsbHostController 意思就是说,我想要把所有的usb controller 都找出来。
所有的,不外乎就是 xhci, ehci, ohci, uhci 
STATUS
EFIAPI
ConnectAllUsbHostController (VOID)
{
  SCT_STATUS Status;
  EFI_PCI_IO_PROTOCOL *PciIo;
  USB_CLASSC UsbClassCReg;
  UINTN NumberOfHandles;
  EFI_HANDLE *HandleBuffer;
  UINTN UsbIndex;
  UINT16 HandleIndex;
  UINT16 UsbIP[] = {PCI_IF_XHCI,   // 3.0
                    PCI_IF_EHCI,   // 2.0
                    PCI_IF_OHCI,   // 1.0  
                                    PCI_IF_UHCI};

  DPRINTF_DEV ("ConnectAllUsbHostController:\n");

  //
  // Connect first layer of PCI device.
  //

  ConnectAllPciDevices ();   // 把各个pci device 长出来。
  只有ConnectAllPciDevices  才能找到 pciio protocol
  Status = gBS->LocateHandleBuffer (
                ByProtocol,
                &gEfiPciIoProtocolGuid,     // 每一个pci device , 都有pciio protocol    
                NULL,
                &NumberOfHandles,
                &HandleBuffer);

  //
  // Connect USB device path according to its type, the ordering is:
  // 1.XHCI 2.EHCI 3.OHCI 4.UCHI
  //

  for (UsbIndex = 0; UsbIndex < sizeof (UsbIP)/sizeof (UINT16); UsbIndex++) {

        HandleIndex = 0;
    while (HandleIndex < NumberOfHandles) {   
      Status = gBS->HandleProtocol (
                      HandleBuffer [HandleIndex],
                      &gEfiPciIoProtocolGuid,
                      &PciIo);
      if (EFI_ERROR (Status)) {
        HandleIndex++;
            continue;
      }

      Status = PciIo->Pci.Read (
                        PciIo,
                        EfiPciIoWidthUint8,
                        PCI_CLASSCODE_OFFSET,
                        sizeof (USB_CLASSC) / sizeof (UINT8),
                        &UsbClassCReg);
      if (EFI_ERROR (Status)) {
        HandleIndex++;
            continue;
      }

      //
      // Test whether the controller belongs to USB type.
      //

      if ((UsbClassCReg.BaseCode == PCI_CLASS_SERIAL) &&
          (UsbClassCReg.SubClassCode == PCI_CLASS_SERIAL_USB) &&
          (UsbClassCReg.PI == UsbIP[UsbIndex])) {

          DPRINTF_DEV (" Handle 0x%x belongs to %x Type USB device Path.\n",
                   HandleBuffer [HandleIndex], UsbIP[UsbIndex]);
          Status = gBS->ConnectController (
                          HandleBuffer [HandleIndex],
                          mContextOverrideDriver,
                          NULL,
                          TRUE);   逐层递归连接,直到没有新的设备句柄产生,逐层连接,我们才能使用usb设备。
          if (!EFI_ERROR(Status)) {
            DPRINTF_DEV ("  Connection success.\n");
          }
          }

      HandleIndex++;
    }
  }

  SafeFreePool (HandleBuffer);

  return SCT_STATUS_SUCCESS;
} // ConnectAllUsbHostController


EFI_STATUS
EFIAPI
ConnectAllPciDevices (VOID)
{
  UINTN Index;
  UINTN NumHandles;
  EFI_STATUS Status;
  EFI_HANDLE *HandleBuffer;

  Index = 0;
  HandleBuffer = NULL;
  Status = EFI_NOT_FOUND;

  DPRINTF_LIB ("ConnectAllPciDevices \n");

  if (mAllPciDeviceStarted) {
    DPRINTF_LIB (" Already happened \n");
    return EFI_SUCCESS;
  }

  gBS->LocateHandleBuffer (
         ByProtocol,
         &gEfiP*otBridgeIoProtocolGuid,  // RootBridge 只有一个
         NULL,
         &NumHandles,
         &HandleBuffer);

  if (NumHandles == 0) {
    DPRINTF_LIB ("  Could not find any Pci Root Bridge devices.\n");
    return EFI_NOT_FOUND;
  }

  for (Index = 0; Index < NumHandles; Index++) {
    Status = gBS->ConnectController (
                    HandleBuffer [Index],
                    NULL,
                    NULL,
                    FALSE);   // 此时,我们只需要找一层,找到device ,能使用pci io 即可。
    DPRINTF_LIB ("  ConnectController return %r.\n", Status);
  }

  //
  // Finally, freed the resource.
  //

  FreePool (HandleBuffer);
  mAllPciDeviceStarted = TRUE;
  DUMP_ALL_DEVICE_PATHS

  return Status;

} // ConnectAllPciDevices


 

上一篇:vim安装bundle和使用


下一篇:python 计算网络基本统计量——度,平均度,度分布