ConnectController()Summary为一个controller 连接一个或多个driverprototypetypedefEFI_STATUSConnectController (IN EFI_HANDLE ControllerHandle,IN EFI_HANDLE *DriverImageHandle OPTIONAL,IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL,IN BOOLEAN Recursive);参数ControllerHandle Controller的handle,供driver连接的。The handle of the controller to which driver(s) tobe connected.DriverImageHandle 一个指向有序支持 EFI_DRIVER_BINDING_PROTOCL的Handle的指针。这个列表以NULL作为结尾。这些handle作为候选者,去管理controller. 这个参数是可选的,可以为NULL,这个参数很典型的应用就是去debug某个driver.RemainingDevicePath A pointer to the device path that specifies a childof the controller specified by ControllerHandle. Thisis an optional parameter that may be NULL. If it is NULL,then handles for all the children of ControllerHandle willbe created. This parameter is passed unchanged to the Supported()and Start() services of the EFI_DRIVER_DINDING_PROTOCOL attached toControllerHandle.Recursive 如果为真,ConnectController()将会被一直调用直到 entiretree of controllers below the controller specified byControllerHandle have been created. 如果为FALSE. Controller树只会被展开一层。解释
CoreConnectController(...)
实现BootServices 的connectController接口,该函数将尝试连接一个或多个驱动程序到一个设备。ControllerHandle 是设备句柄,DriverImageHandle 优先选择的驱动程序句柄。RemaingDevicePath将被传入驱动程序DriverBinding->Supported()和Drivebinding->Start()接口,当其为空时,驱动程序将创建所有的子设备,否则将只创建RemainingDevicePath指定的子设备。Recursive 为TRUE 时,该函数将尝试逐层递归连接,直至没有新的设备句柄产生,RemainingDevicePath 此时会被忽略。
EFI_STATUS
EFIAPI
CoreConnectController(
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE *DriverImageHandle
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
IN BOOLEAN Recursive
)
{
...
//
// Make a copy of RemainingDevicePath to guanatee it is aligned
//
AlignedRemainingDevicePath = NULL;
if (RemainingDevicePath != NULL) {
AlignedRemainingDevicePath = DuplicatedDevicePath(RemainingDevicePath);
if (AlignedRemaindingDevicePath == NULL) {
return EFI_OUT_OF_RESOUCES;
}
}
//
// Connect all drivers to ControllerHandle
// If CoreConnectSingleController returns EFI_NOT_READY, then the number of
// Driver Binding Protocols in the database has increased during the call so the connect operation must be restarted
//
do {
ReturnStatus = CoreConnectSingleController(
ControllerHandle,
DriverImageHandle,
AlignedRemainingDevicePath
);
} while (ReturnStatus == EFI_NOT_READY);
//
// Free the aligned copy of RemaingingDevicePath
//
// Free the aligned copy of RemainingDevicePath
//
if (AlignedRemainingDevicePath != NULL) {
CoreFreePool(AlignedRemainingDevicePath);
}
调用CoreConnectSingleController() 连接驱动程序到设备。
在函数调用过程中如果有新的驱动程序被发现,CoreConnectSingleController() 返回EFI_NOT_READY, 此时我们将重新调用该函数。
//
// Count 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) {
ChildHandleCount++;
}
}
}
Allocate a handle buffer for ControllerHandler's children
ChildHanldeBuffer = AllocatePool(ChildHandleCount * sizeof (EFI_HANDLE));
if (ChildHandleBuffer == NULL) {
CoreReleaseProtocollock();
return EFI_OUT_OF_RESOURCES;
}
//
// 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) {
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
);
}
CoreConnectSingleController(...)
该函数尝试连接一个或多个驱动程序到指定设备。
EFI_STATUS
CoreConnectSingleController(
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE *ContextDriverImageHandles
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
{
//
// Get list of all Driver Binding Protocol Instance
//
Status = CoreLocateHandleBuffer(
ByProtocol,
&gEfiDriverBindingProtocolGuid,
NULL,
&DriverBindingHandleCount,
&DriverBindingHandleBuffer
);
if (EFI_ERROR( Status) || (DriverBindingHandleCount == 0) {
return EFI_NOT_FOUND;
}
//
// Allocate a duplicate array for the sorted Driver Binding Protocol Instance
SortedDriverBindingProtocols = AllocatePool(sizeof(VOID *) * DriverBindingHandleCount);
if (