从功能上划分,UEFI驱动可以分为以下类别:
- 符合UEFI驱动模型的驱动,包括总线驱动、设备驱动和混合驱动,一般用来驱动对应的硬件设备
- 服务性驱动,这类驱动不管理任何设备,一般用来产生Protocol
- 初始化驱动,不产生任何句柄,也不增加任何Protocol到系统数据库,主要用来进行一些初始化操作,操作完就会从系统内存中卸载
- 根桥型驱动,用来初始化平台上的根桥控制器,并产生一个设备地址Protocol,以及访问总线设备的Protocol,一般通过总线驱动访问设备。
在UEFI模块中驱动有两种类型:DXE_DRIVER 和 UEFI DRIVER,
驱动程序包含有硬件设备的信息,有了这些信息计算机就可以和设备进行通信,一个完整的驱动框架至少要完成以下任务:
- 找到支持的硬件设备
- 安装驱动到此硬件设备
- 从硬件设备卸载驱动
UEFI驱动模型的核心是通过EFI Driver Binding Protocol管理驱动程序,一个完整的驱动程序包含两个核心部分:EFI Driver Binding Protocol以及驱动服务本身。作为一个用户友好的驱动程序,通常它还要包括一个EFI Component Name Protocol。
首先来看UEFI驱动模型是如何管理驱动的。在UEFI驱动的入口函数函数中,安装EFI Driver Binding Protocol(EDBP)到某个Handle(大部分是自身,即ImageHandle),这个EBDP实例会常驻内存,用于驱动的安装和卸载。使用EBDP使得我们可以多次操作(查找设备、安装卸载)驱动。其代码原型为:
(1)Supported函数
Supported函数用于检查一个设备控制器是否支持该驱动。其函数原型为:
(2)Start函数
Start函数用来将驱动安装到设备上并启动硬件设备,在函数中最重要的事情是调用InstallProtocolInterface()或者InstallMutipleProtocolInterface()在ControllerHandle上安装驱动protocol,其函数原型为:
(3)Stop函数
Stop函数用于停止硬件设备并卸载驱动(调用UninstallProtocolInterface()或UninstallMultipleProtocolInterfaces()从ControllerHandle卸载驱动协议)。其代码原型为:
UEFI驱动程序框架:
加载驱动的整体过程为:首先在Shell中使用命令load将驱动文件加载到内存,加载后UEFI会调用gBS->StartImage()执行DriverImage的入口函数,在入口函数里面,Driver Binding被加载到Handle上(Driver Image handle或者其它的Controller handle),然后UEFI会遍历所有的控制器,为每个控制器调用CoreConnectSingleController中会调用EDBP的Supported函数测试驱动是否支持该控制器,如果支持,则调用Start()安装驱动。
UEFI驱动加载后,会枚举设备,然后调用UEFI Driver Binding Protocol(EFI_DRIVER_BINGDING_PROTOCOL) 的support()函数,用来判断驱动是否支持枚举的这个Controllerhandle,如果支持就调用EFI_DRIVER_BINGDING_PROTOCOL的Start()函数,这个函数申请内存资源和初始化内部变量,安装需要的Protocol和初始化硬件。
通常驱动都还有一个可打印的名字,便于向用户显示驱动的信息。这个可打印名字是由EFI Component Name Protocol (ECNP)或EFI Component Name2 Protocol (ECN2P)提供的,这两个不是驱动必需的Protocol,但建议驱动开发者提供这个protocol,其函数原型为
驱动可以分为两部分,一部分是硬件相关的部分,这部分是驱动的内容,用于硬件设备,为用户提供服务,以协议的形式,如DiskIO、BlockIo;另一部分是驱动的框架部分,需要实现Driver Binding Protocol,主要是三个接口(Supported、Start和Stop),这部分用于实现框架部分。
以AC97为例来介绍驱动的编写:
驱动的硬件部分主要是驱动的内容,定义PROTOCOL,提供PROTOCOL中定义的服务函数的原型、PROTOCOL的私有数据结构体、PROTOCOL的服务函数的实现
audio.h 定义EFI_AUDIO_ROTOCOL相关结构体,
定义EFI_AUDIO_PROTOCOL的GUID,
定义protocol提供的服务的函数原型,其中包括Reset、Play、Volume
在accdriver.c中,定义 用于标识音频播放的上下文的数据结构,一般命名为X_PRIVATE_DATA。在上下文中,要包含一个驱动实例,以及其他的设备相关信息。具体到EFI_AUDIO_PROTOCOL,在上下文中要包含EFI_AUDIO_PROTOCOL实例、设备的EFI_PCI_IO_PROTOCOL实例和BufferDescriptor:
定义一个私有数据结构体,用来存储PROTOCOL的私有数据,通过建立私有数据的结构,并将This指针包含其中,所有的接口函数都可以通过This指针发现私有数据的内存位置,从而获得需要共享的私有数据。
定义一个EFI_AUDIO_PROTOCOL模板,这个模板用于初始化EFI_AUDIO_PROTOCOL实例:
定义AUDIO_PRIVATE_DATA_FROM_THIS宏,用于根据This指针找到设备上下文
下面实现EFI_AUDIO_PROTOCOL中定义的三个服务,每个成员函数(服务)的第一个参数是This指针,在函数里面根据This指针获得上下文Private,然后根据上下文执行相应操作。
驱动的框架部分主要完成三个功能:
- 实现EFI_DRIVER_BINDING_PROTOCOL(EDBP)
- 实现Component Name Protocol 和 Component Name2 Protocol
- 在模块的初始化函数中安装EDBP、ECNP和ECN2P
(1)实现EFI_DRIVER_BINDING_PROTOCOL(EDBP)
关键是实现EDBP的三个服务:Surpported、Start和Stop。
首先产生一个EDBP实例并初始化:
然后实现三个核心服务(Supported、Start和Stop)
实现Supported服务
函数AC97DriverBindingSupported实现了Supported服务,当检测的设备是AC97控制器时,返回EFI_SUCCESS,否则返回错误代码。其处理流程为:
判断Controller是否有EFI_PCI_IO_PROTOCOL,若没有,则返回错误
读取PCI配置空间,根据配置空间的ClassCode判断设备是否是AC97驱动器
实现Start服务
AC97DriverBindingStart实现了Start服务,其功能是启动AC97设备并安装EFI_AUDIO_PROTOCOL。启动过程包括三个部分:
打开EFI_PCI_IO_PROTOCOL
为AC97控制器上下文分配内存
在ControllerHandle上安装AC97驱动Protocol,即EFI_AUDIO_PROTOCOL
实现Stop服务
AC97DriverBindingStop函数实现了Stop服务,同Start函数相对应,其主要过程包括三部分:
关闭设备控制器上的PCI IO Protocol
卸载ControllerHandle上的Audio IO Protocol
释放资源
(2)实现ECNP和ECN2P
作为一个完整的、对用户友好的驱动程序,我们还要提供ECNP和ECN2P
(3)安装EDBP、ENCP和EN2CP
最后要在模块的入口函数内安装EDBP、ENCP和ECN2P这三个Protocol
EfiLibInstallDriverBindingComponentName2是UefiLib提供的用于安装Driver Binding Protocol、Component Name Protocol 及 Component Name2 Protocol的函数
然后编写AC97驱动的工程文件
到此这篇vgasave驱动(vgadriver是什么驱动)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/rfx/24740.html