uefi drivers 是指在inf中將MODULE_TYPE指定爲UEFI_DRIVER。例如inf的例子
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = DiskIoDxe
MODULE_UNI_FILE = DiskIoDxe.uni
FILE_GUID = 6B38F7B4-AD98-40e9-9093-ACA2B5A253C4
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = InitializeDiskIo
從這個inf中可以看到這個uefi的driver name爲DiskIoDxe,其入口函數爲InitializeDiskIo
在uefi driver中一般會用到EFI_DRIVER_BINDING_PROTOCOL/EFI_COMPONENT_NAME_PROTOCOL/EFI_COMPONENT_NAME2_PROTOCOL/EFI_DRIVER_DIAGNOSTICS2_PROTOCOL 這四個protocol.
如下所示:
EFI_STATUS
EFIAPI
InitializeDiskIo (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
//
// Install driver model protocol(s).
//
Status = EfiLibInstallDriverBindingComponentName2 (
ImageHandle,
SystemTable,
&gDiskIoDriverBinding,
ImageHandle,
&gDiskIoComponentName,
&gDiskIoComponentName2
);
ASSERT_EFI_ERROR (Status);
return Status;
}
在其入口函數InitializeDiskIo 中通過EfiLibInstallDriverBindingComponentName2 註冊driver,
EFI_STATUS
EFIAPI
EfiLibInstallDriverBindingComponentName2 (
IN CONST EFI_HANDLE ImageHandle,
IN CONST EFI_SYSTEM_TABLE *SystemTable,
IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding,
IN EFI_HANDLE DriverBindingHandle,
IN CONST EFI_COMPONENT_NAME_PROTOCOL *ComponentName, OPTIONAL
IN CONST EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2 OPTIONAL
)
{
EFI_STATUS Status;
ASSERT (DriverBinding != NULL);
//
// Update the ImageHandle and DriverBindingHandle fields of the Driver Binding Protocol
//
DriverBinding->ImageHandle = ImageHandle;
DriverBinding->DriverBindingHandle = DriverBindingHandle;
if (ComponentName == NULL || FeaturePcdGet(PcdComponentNameDisable)) {
if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) {
Status = gBS->InstallMultipleProtocolInterfaces (
&DriverBinding->DriverBindingHandle,
&gEfiDriverBindingProtocolGuid, DriverBinding,
NULL
);
} else {
Status = gBS->InstallMultipleProtocolInterfaces (
&DriverBinding->DriverBindingHandle,
&gEfiDriverBindingProtocolGuid, DriverBinding,
&gEfiComponentName2ProtocolGuid, ComponentName2,
NULL
);
}
} else {
if (ComponentName2 == NULL || FeaturePcdGet(PcdComponentName2Disable)) {
Status = gBS->InstallMultipleProtocolInterfaces (
&DriverBinding->DriverBindingHandle,
&gEfiDriverBindingProtocolGuid, DriverBinding,
&gEfiComponentNameProtocolGuid, ComponentName,
NULL
);
} else {
Status = gBS->InstallMultipleProtocolInterfaces (
&DriverBinding->DriverBindingHandle,
&gEfiDriverBindingProtocolGuid, DriverBinding,
&gEfiComponentNameProtocolGuid, ComponentName,
&gEfiComponentName2ProtocolGuid, ComponentName2,
NULL
);
}
}
//
// ASSERT if the call to InstallMultipleProtocolInterfaces() failed
//
ASSERT_EFI_ERROR (Status);
return Status;
}
我們這裏的ComponentName和ComponentName2 都不是NULL,因此走else的case,即
Status = gBS->InstallMultipleProtocolInterfaces (
&DriverBinding->DriverBindingHandle,
&gEfiDriverBindingProtocolGuid, DriverBinding,
&gEfiComponentName2ProtocolGuid, ComponentName2,
NULL
);
通過gBS的InstallMultipleProtocolInterfaces,向DriverBinding->DriverBindingHandle註冊兩個guid。這裏的DriverBinding->DriverBindingHandle也是在EfiLibInstallDriverBindingComponentName2 中賦值
DriverBinding->ImageHandle = ImageHandle;
DriverBinding->DriverBindingHandle = DriverBindingHandle;
這裏的DriverBindingHandle也就對應InitializeDiskIo中的ImageHandle也就是這個binary本身.
這樣當調用 gBS->loadImage將驅動文件加載到內存後,再調用 Status = gBS->StartImage (ImageHandle, ExitDataSize, ExitData);就會call到入口函數
StartImage從是通過 Image->Status = Image->EntryPoint (ImageHandle, Image->Info.SystemTable);調用到入口函數的,針對本例就是調用InitializeDiskIo。
而InitializeDiskIo 最重要的是實現了gDiskIoDriverBinding,
EFI_DRIVER_BINDING_PROTOCOL gDiskIoDriverBinding = {
DiskIoDriverBindingSupported,
DiskIoDriverBindingStart,
DiskIoDriverBindingStop,
0xa,
NULL,
NULL
};
gDiskIoDriverBinding 實現了三個函數,DiskIoDriverBindingSupported用與見識是否支持這個driver,如果支持的話,就調用DiskIoDriverBindingStart,在DiskIoDriverBindingStart 中就可以將驅動安裝到設備上並啓動硬件設備
DiskIoDriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
)
{
//
// Install protocol interfaces for the Disk IO device.
//
if (Instance->BlockIo2 != NULL) {
Status = gBS->InstallMultipleProtocolInterfaces (
&ControllerHandle,
&gEfiDiskIoProtocolGuid, &Instance->DiskIo,
&gEfiDiskIo2ProtocolGuid, &Instance->DiskIo2,
NULL
);
} else {
Status = gBS->InstallMultipleProtocolInterfaces (
&ControllerHandle,
&gEfiDiskIoProtocolGuid, &Instance->DiskIo,
NULL
);
}
}
在DiskIoDriverBindingStart 中一般會調用InstallMultipleProtocolInterfaces或者InstallProtocolInterfaces來在ControllerHandle 上安裝protocol.
後面的其他程序就可以通過gEfiDiskIoProtocolGuid 或者 gEfiDiskIo2ProtocolGuid來得到Instance->DiskIo或者Instance->DiskIo2。
例如下面的例子
Status = gBS->OpenProtocol (
Entry->PartitionHandle,
&gEfiDiskIoProtocolGuid,
(VOID **) &DiskIo,
gImageHandle,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
ASSERT_EFI_ERROR (Status);
Status = DiskIo->WriteDisk (DiskIo, MediaId, 0, Size, Image);
就通過gEfiDiskIoProtocolGuid 來調用DiskIo->WriteDisk
---------------------
作者:tiantao2012
來源:CSDN
原文:https://blog.csdn.net/tiantao2012/article/details/72458172
版權聲明:本文爲博主原創文章,轉載請附上博文鏈接!
uefi driver
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.