uefi driver

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 
版權聲明:本文爲博主原創文章,轉載請附上博文鏈接!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章