Dxe Driver可以视作UEFI中的一个服务,在entry中通过protocol安装自己的服务,在Bds等位置通过locate protocol使用该服务,不必依赖与具体的硬件。当需要封装某个设备/控制器或总线的时候,对应于具体的物理实现,需要用到UEFI Driver的模型实现。UEFI Driver模型实现设备/总线的检测,安装,卸载,更新,启动,停止等;一个Driver可能适配多个设备,一个设备可能连接管理多个子设备等,因此UEFI Driver还可以多次安装。以下从GraphicsOutput设备为入口来解读UEFI driver的源码。
1. UEFI Driver的实现
源码路径为MdeModulePkg\Universal\Console\GraphicsOutputDxe\GraphicsOutput.c。从driver的入口开始:
InitializeGraphicsOutput (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
// 从PEI阶段的HOB中获取Graphic的信息,如Edid等
HobStart = GetFirstGuidHob (&gEfiGraphicsInfoHobGuid);
// 将mGraphicsOutputDriverBinding 安装到Dxe环境里面
Status = EfiLibInstallDriverBindingComponentName2 (
ImageHandle,
SystemTable,
&mGraphicsOutputDriverBinding,
ImageHandle,
&mGraphicsOutputComponentName,
&mGraphicsOutputComponentName2
);
return Status;
}EfiLibInstallDriverBindingComponentName2()根据入参以及实际pcd的配置安装driver的protocol和名字等信息;
Status = gBS->InstallMultipleProtocolInterfaces (
&DriverBinding->DriverBindingHandle,
&gEfiDriverBindingProtocolGuid, DriverBinding,
&gEfiComponentNameProtocolGuid, ComponentName,
&gEfiComponentName2ProtocolGuid, ComponentName2,
NULL
);驱动模型的核心通过EFI_DRIVER_BINDING_PROTOCOL实现,通过该protocol判断一个driver是否支持某个控制器,以及启动和停止该控制器;
struct _EFI_DRIVER_BINDING_PROTOCOL {
EFI_DRIVER_BINDING_SUPPORTED Supported; //判断driver是否支持该控制器
EFI_DRIVER_BINDING_START Start; //安装driver到设备/总线控制器
EFI_DRIVER_BINDING_STOP Stop; //卸载设备/总线控制器driver
UINT32 Version;
EFI_HANDLE ImageHandle; //当前driver的image handle
EFI_HANDLE DriverBindingHandle; //该protocol应该安装到的handle,大部分时候与ImageHandle相同,如果
};
graphicsOutput的实现为:
EFI_DRIVER_BINDING_PROTOCOL mGraphicsOutputDriverBinding = {
GraphicsOutputDriverBindingSupported,
GraphicsOutputDriverBindingStart,
GraphicsOutputDriverBindingStop,
0x10,
NULL,
NULL
};EFI_COMPONENT_NAME_PROTOCOL/EFI_COMPONENT_NAME2_PROTOCOL 描述Driver的名字,提供获取driver名字和控制器名字的接口,支持的语言类型;
struct _EFI_COMPONENT_NAME2_PROTOCOL {
EFI_COMPONENT_NAME2_GET_DRIVER_NAME GetDriverName;
EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME GetControllerName;
CHAR8 *SupportedLanguages;
};
graphicsOutput的实现为:
// EFI Component Name Protocol
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL mGraphicsOutputComponentName = {
GraphicsOutputComponentNameGetDriverName,
GraphicsOutputComponentNameGetControllerName,
"eng"
};
// EFI Component Name 2 Protocol
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL mGraphicsOutputComponentName2 = {
(EFI_COMPONENT_NAME2_

发布评论