connnectController分析(暂未插图)

1.      CoreConnectController函数

1.1.     函数介绍

实现BootServices 的connectController接口,该函数将尝试连接一个或多个驱动程序到一个设备。ControllerHandle 是设备句柄,DriverImageHandle 优先选择的驱动程序句柄。RemaingDevicePath将被传入驱动程序DriverBinding->Supported()和Drivebinding->Start()接口,当其为空时,驱动程序将创建所有的子设备,否则将只创建RemainingDevicePath指定的子设备。Recursive 为TRUE 时,该函数将尝试逐层递归连接,直至没有新的设备句柄产生,RemainingDevicePath 此时会被忽略。

在MdeModulePkg/Core/Dxe/hand这个文件夹中,存在对CoreConnectController的定义。

 

         这个函数正式UEFI驱动为了上报系统盘使用的函数:

 

         这里看一下这个上报盘的函数都做了哪些事:

 

         我们在这个接口调用的时候,使用的参数是(channel->channelHandle, NULL, NULL, TRUE)。

         整个bootservice的定义位置如下所示:

 

1.2.     主函数分析

第一个参数:

         指向需要连接的控制器的handle

第二个参数:

         指向一个支持driverbinding协议的链表

第三个参数:

         由控制卡handle指定的一个子handle的devicepath信息

 

1.2.1.     参数有效性判断

函数执行的第一步是进行handle是否有效的判断:

 

         判断的原则就是遍历所有的handle列表,判断判断当前的handle是否与给定的handle是一致的,若是一致的,则返回EFI_SUCCESS;否则返回EFI_INVALID_PARAMETER。

 

1.2.2.     赋值devicePath的备份

         为了保证输入参数不被损坏,拷贝一个备份。

 

1.2.3.     将所有的drivers连接到控制卡handle

 

         这里进行一个循环,只要连接的结果返回是EFI_NOT_READY,就表示当前在handle列表里面存在的driver handle协议是增加的了,连接操作需要重复执行一次。

1.2.4.     是否需要遍历子handle

         只要改函数第4个传入的参数是TRUE,就会对该handle的所有子handle进行连接操作。

 

1.2.5.     返回

         该函数在确认所有需要遍历的handle都被遍历了之后,便会返回ReturnStatus,主要涉及的返回值位置如下所示:

 

 

1.3.     CoreConnectSingleController

         该函数的作用主要是将控制器和驱动之间创建联系。

1.3.1.     第一步:初始化本地变量

 

1.3.2.     第二步:获取当前环境下的所有driverbinding协议

 

1.3.3.     第三步:为获取到的driverbinding协议进行排序

         先申请到一个足够到的内存空间:

 

         若传入的需要连接的device列表不是空的,那就将对应的协议放到这个排序的列表中:

 

1.3.4.     第四步:进行driver override 协议的绑定

         首先找到当前环境下面的Platform Driver Overrid协议,这个协议的作用是将驱动连接到当前的控制器上。

 

1.3.5.     第五步:进行driver family override 协议的绑定

         当该主函数传入的最后一个参数是TRUE,才会进行driver family override协议的绑定。否则不会执行:

 

1.3.6.     第六步:进行specific driver override协议的绑定

1.3.7.     第七步:将剩余driver bingding协议加入到排序列表里

 

1.3.8.     第八步:判断当前的流程是否是否启动完成

         若新查找的driverbinding协议增加了,说明流程处理是没有准备好的,需要重复处理该流程。

 

1.3.9.     第九步:进行剩余driverbinding协议的排序

         将剩余的协议使用版本从高到底的顺序进行排序

 

1.3.10.  第十步:执行所有的driverbinding协议

 

第十步:返回值

         在当前的控制器上有驱动执行成功;在没有驱动执行成功,但是遍历了devicepath节点,也会返回成功。

 

1.4.     递归连接所有控制卡handle的子选项

1.4.1.     使用的代码说明

         在调用到这个函数的时候,会执行以下的代码:

 

         屏蔽掉这行代码:

 

新存在的打印是:

 

         可以确认在存在这行代码的时候,可以触发getNextTargetLun这个函数。

1.4.2.     基本数据结构

查看当前驱动的handle结构体:

 

         按照UEFI handle的定义,每个handle都是在这样的一个列表里面。

         每在一个handle上安装了一个协议,就会存在一个对应的PROTOCOL_INTERFACE结构,具体显示如下:

 

1.4.3.     获取子handle的数量

         从指向的流程中可以知道对于每一个handle,都是在一个循环链表里面。这个链表里面极了。初步的理解为,以下的操作是:遍历所有的同类型handle链表,找到所有open属性是child的,将这些handle分别进行处理。

 

         每在一个handle上绑定一个协议,就会存在一个PROTOCOL_INTERFACE结构的存在。这里遍历Handle列表,将该列表中的每一个绑定的协议遍历,观察是否存在打开属性是EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER的协议。存在的话将计数加一。

1.4.4.     获取所有的子handle的buffer

         按照之前的流程,获取所有的子handle:

 

1.4.5.     对所有的子handle执行连接操作

 

1.5.     分析结论

         这个函数的作用,实际上的作用就是在当前的控制器上连接一个或者多个的驱动。当后面的第二和第三个参数是空的时候,会对当前控制器上所有的驱动都连接一遍。连接一遍的意思就是,对该控制器上的所有驱动都执行一次driverbinding协议,从support函数入手,一直走完start函数。这也是为什么么会走到我们当前控制卡的support接口。该函数也会对SCSI bus的驱动进行再次的连接:

 

         以至于我们的打印信息里面存在resetTargetLun的打印。

         每次调用connectController函数,传入的imagehand是固定的,这就导致我们看到的driverBinding函数会被不断的调用,且存在不同的handle号了。

 

2.      CoreDisconnectController函数

2.1.     函数介绍

将控制器与驱动之间的连接断开

2.2.     主函数分析

2.2.1.     参数分析

 

       该函数传入三个参数,分别是控制卡handle、设备handle和子设备handle。这个函数的参数命名存在一定的误导性。这里的驱动模型与linux下面的一致,connect与disconnect的就是驱动和设备。这里也能明白一个道理,存在一个驱动,就会存在一个handle,存在一个设备也会存在一个handle。

       根据开发的选择不同,一个驱动可以连接多个设备;一个设备也能连接多个驱动。关键看我们人为的怎么处理。

       ps3rom的驱动要求与设备之间是1对1的关系。

2.2.2.     确认当前的handle是有效的

 

2.2.3.     重要结构体分析

 

       这样的一个数据结构,里面记录了当前使用的控制卡handle和设备handle。以及需要使用的属性。

2.2.4.     判断是否指定了agentHandle

 

       当没有指定agentHandle的时候,会遍历所有的ctrlHandle。找到所有agentHandle的OpenData节点,判断这个节点是否满足EFI_OPEN_PROTOCOL_BY_DRIVER。若是满足,会将计数不断加一。

2.2.5.     获取所有的agenthandle

 

       收集当前的所有agentHandle

2.2.6.     获取当前控制器的driverbinding协议

 

       根据driverImageHandle来获取当前绑定在设备上的driverdinding协议。具体调用的底层接口是:

 

2.2.7.     判断是否有子handle

 

 

2.2.8.     执行stop操作

 

       执行stop函数。

 

posted @ 2023-03-14 23:36  free-锻炼身体  阅读(106)  评论(0编辑  收藏  举报