uefi driver

来源:互联网 发布:淘宝刷手一天真实收入 编辑:程序博客网 时间:2024/06/11 02:56
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


原创粉丝点击