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