固件C字营·武汉·版权所有
-------------------------------------------------------------------------------电脑--------------------------------------------------
同一个UEFI driver可能需要管理多个设备,对于每一个设备我们需要为其分配单独的私有的数据,所以我们不能奢望用全局的数据在不同的设备之间共享数据的通道,并且我们还需要保持设计的driver是可重入的。每一个设备或者说是控制器我们需要为其分配独立的私有数据,这些数据主要包括:
? A signature for the data structure
? The handle of the controller or the child that is being managed or produced
? The group of protocol interfaces that are being consumed
? The group of protocol interfaces that are being produced
? Private data fields and services that are used to manage a specific controller
为了在私有数据结构里面通过一个指向结构里面的一个公共的数据结构指针来获取私有结构的访问路径,我们使用一个CR()的宏定义来完成这一过程,这个类似于面向对象语言C++中的This 指针,但是由于UEFI是用C来写的,缺少了面向对象的特性,所以就用这种方法来模拟面向对象的特性。
以下的宏定义只需要提供私有数据的结构类型,结构中包含的公共数据的指针,公共数据的类型通过在公共数据指针的基础上减去公共数据距离私有数据顶部的偏移地址的方法来获取私有数据结构的指针,然后通过强制了类型转换,就能获取到私有数据的指针,我们亦可以把得到的指针当做是This指针。之后我们就可以使用这个This指针来索引私有数据结构里面的所有的数据了,是不是很方便!以下是详细的code,大家可以仔细读一读。
以下便是一个我们常用的例子,现在让我们看一看里面都有些什么:
1.第一行,我们定义个signature,这个是在前面没有提到的,这里的主要作用的对我们的私有数据做一个标签,以此来方便diagnosis工具或者其他的工具代码来校验这个私有数据结构是否是我们需要的哪一个。在CR宏定义中我们一般会加入对这个signature的校验,如果校验结果不符合,就可以抛出异常
2.定义一个HDD的控制器的简单示范,他包含三个数据项:
a>定义该设备私有数据的signature
b>定义该设备产生的protocol
c>定义该设备需要消费的protocol,一般使用指针来表示
3.最后的是一个通过driver生产的protocol的指针来获取私有数据的宏定义.
其中DiskIo protocol是由driver自己生产的,使用BS service的allocate pool服务来申请内存,让后把service copy到每一个需要安装driver的设备或者说是控制器上.以下是一个示例:
1.前面的部分是包含一些 电脑 必备的头文件,包括uefi头文件,三个protocol的定义头文件以及一个memory库头文件
2.第二部分定义了,我们的私有数据的模板,我们要在这里实现数据的signature,DiskIoReadDisk以及DiskIoWriteDisk这两个函数的实现及其定义声明,最后用一个NULL来结束。同时我们需要注意这里的模板是一个全局的数据变量。
3.第三部分在driver的DriverBinding protocol的start方法中我们会去申请一块内存,并且把我们的上面生成的数据模板拷贝到申请的内存块中,最后判断是否成功,是否需要抛出异常。
同理在DriverBinding protocol里面的stop方法中,我们需要释放申请的内存和销毁我们为每个设备或者是控制器绑定的私有数据空间。细节看下面的示例:这里使用到了CR()从DiskIo protocol指针来索引私有数据指针,然后使用memory 服务释放内存。
全文主要探讨了UEFI 驱动模型的driver中私有数据及driver的protocol生产消费模型中各个protocol是如何与设备绑定,以及如何释放资源的,非UEFI驱动模型的设备也需要参考这个模式来执行,以此来保证一致性及易于处理。
敬请关注微信公众号:“固件C字营”
敬请关注今日头条号:”固件C字营“