EFI Driver Model(上)

EFI Driver Model(上)

主要参考UEFI_SPEC,再加上自己的理解总结

1、Driver 与Application 的区别

   Application :可以被Boot Manager和其它UEFI应用加载,要加载UEFI应用程序,固件分配足够的内存来保存映像,将UEFI应用程序映像中的部分复制到分配的内存。一旦完成,所分配的内存将被设置为针对图像的代码和数据的适当类型。然后,控件被转移到UEFI应用程序的入口点。当应用程序从其入口点返回时,或当它调用引导服务EFI_BOOT_SERVICES.exit()后,UEFI应用程序从内存中卸载,控件返回到加载UEFI应用程序的UEFI组件。
  Drivers:由引导管理器、符合本规范的固件或其他UEFI应用程序加载。要加载UEFI驱动程序,固件分配足够的内存来保存映像,将UEFI驱动程序映像中的部分复制到分配的内存,并应用所需的重定位修复。一旦完成,所分配的内存将被设置为针对图像的代码和数据的适当类型。如果UEFI驱动程序返回EFI_SUCCESS的状态代码,则不会从内存中卸载。如果UEFI驱动程序的返回代码是一个错误状态代码,则该驱动程序将从内存中卸载。

2、EFI驱动模型目标

  UEFI驱动程序模型被设计为通用的,可以适用于任何类型的总线或设备。UEFI规范描述了如何编写PCI总线驱动程序、PCI设备驱动程序、USB总线驱动程序、USB设备驱动程序和SCSI驱动程序。提供了其他细节,允许UEFI驱动程序存储在PCI选项ROM中,同时保持与遗留选项ROM映像的兼容性
  • 不需依赖Dependency来决定执行顺序
  • 必须可以被重复执行 (ex.FAT, USBKBD)
  • 不需要实时启动 (ex.USBKBD)
  • 支持硬件的热插拔(Hot-Plug) (ex.USBKBD)
  • 支持软件的热插拔(Unload) (Unload Driver)
  • 所有的Function都是Device(Handle)结合Driver(Protocol)所达成

3、EFI驱动模型

3.1 Legacy Option ROM Issues

  Legacy Rom有许多限制和限制,这些限制限制了平台设计者和适配器供应商的创新。为了改进传统rom,
  •UEFI驱动程序模型的设计注意事项:
  • 驱动程序需要平面内存模式,系统可以完全访问组件。
 . •驱动程序需要用C语编写,以便它们可以在处理器架构之间进行可移植。
 . •驱动程序可以编译成虚拟机可执行文件,允许单个二进制驱动程序在使用不同处理器架构的机器上工作。

3.2 驱动初始化

  驱动程序映像的文件必须从某种类型的媒体中加载。这可能包括ROM、闪存、硬盘驱动器、软盘驱动器、CD-ROM,甚至是网络连接。一旦找到了驱动程序映像,就可以通过引导服务EFI_BOOT_SERVICES.LoadImage().将其加载到系统内存中。驱动程序的句柄被创建,并在该句柄上放置一个已加载的图像协议实例。此时,驱动程序存在内存中等待被启动。通过EFI_BOOT_SERVICES.StartImage()启动Image.

3.3Host Bus Controllers

  驱动程序不允许触摸驱动程序入口点中的任何硬件.因此,驱动程序将被加载并启动,但它们都将等待被告知管理系统中的一个或多个控制器。一个平台组件,如Boot Manager,负责管理驱动程序与控制器的连接.然而,在建立第一个连接之前,必须有一些初始的控制器集合供驱动程序管理。这个控制器集合称为主机总线控制器.主机总线控制器提供的I/O抽象是由UEFI驱动程序模型范围之外的固件组件产生的。例如,一个PCI主机总线控制器支持一个或多个由PCI根桥I/O协议抽象出来的PCI根桥。
  • 管理部分 Core Chipset
  • 直接操作硬件
  • 创建一个或多个 Root Bridge Handles
  • Produces Root Bridge I/O Protocols
  • Installed onto new Root a Bridge Handles

3.4 Device Drivers

  设备驱动程序不允许创建任何新的设备句柄。相反,它会在现有的设备句柄上安装其他的协议接口。最常见的设备驱动程序类型将I/O抽象附加到总线驱动程序创建的设备句柄。一些示例I/O抽象将包括简单文本输出、简单输入、块I/O和简单网络协议。连接设备句柄的设备驱动程序必须在其自己的映像句柄上安装了驱动程序绑定协议.。

  • Initialize
    • 安装DriverBindingProtocols到DXE Core
      -+ Support
      -+ Start
      -+ Stop
  • Support
    • 询问是否可以支持传入的Handle
  • Start
    • 连接Driver与Handle
  • Stop
    • 断开Driver跟Handle之间的连结

3.5 Bus Drivers

  从UEFI驱动程序模型的角度来看,总线驱动程序和设备驱动程序实际上是相同的。唯一的区别是,总线驱动程序为总线驱动程序在其总线上发现的子控制器创建了新的设备句柄。因此,总线驱动程序比设备驱动程序稍微复杂一些,但这反过来又简化了设备驱动程序的设计和实现.总线驱动主要有两种类型。第一个是在第一次调用Start()时为所有子控制器创建句柄。另一种类型Start()创建多个调用创建子控制器的句柄。
  • 管理或枚举总线控制器
  • Start() 创建一个或多个 Child Handles
  • Start() Produces Bus Specific I/O Protocols • Installed onto the Bus’s Child Handles

3.6 Platform Components

  在UEFI驱动程序模型下,连接和切断驱动程序与平台控制器的行为受平台固件的控制。这通常将作为UEFI引导管理器的一部分来实现,但也可以实现其他实现.启动服务EFI_BOOT_SERVICES.ConnectController() 和
EFI_BOOT_SERVICES.DisconnectController()可以被平台固件用来确定哪些控制器启动,哪些不启动。

3.7 热插拔事件

  以前系统固件不需要处理预启动环境中的热插拔事件,然而,随着像USB这样的总线的出现,终端用户可以在任何时候添加和删除设备,确保能够在UEFI驱动程序模型中描述这些类型的总线是很重要的。总线驱动程序支持热添加和删除设备,从而为此类事件提供支持。例如,当键盘被热添加到平台上的USB总线时,最终用户会期望键盘处于活动状态。USB总线驱动程序可以检测到热添加事件,并为键盘设备创建一个子句柄.但是,只有当EFI_BOOT_SERVICES.ConnectController()被调用,驱动连接到控制器,键盘才能变成活跃设备。使用EFI_BOOT_SERVICES.DisconnectController() 断开控制器,删除热插拔。

3.8 EFI Services Binding

  UEFI驱动程序模型可以很好地映射到硬件设备、硬件总线控制器和叠加在硬件设备之上的软件服务的简单组合上。
EFI – Start

EFI_STATUS 
SataControllerStart ( 
   IN EFI_DRIVER_BINDING_PROTOCOL *This, 
   IN EFI_HANDLE Controller, 
   IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 
 ) { 
  EFI_STATUS Status; 
  EFI_PCI_IO_PROTOCOL *PciIo; 
  EFI_SATA_CONTROLLER_PRIVATE_DATA *SataPrivateData; 
  Status = gBS->OpenProtocol ( 
        Controller, 
        &gEfiPciIoProtocolGuid, 
        (VOID **)&PciIo, 
        This->DriverBindingHandle,
         Controller, EFI_OPEN_PROTOCOL_BY_DRIVER
          ); 
   //
   // Allocate SATA private data structure 
   //
   Status = gBS->AllocatePool ( 
         EfiBootServicesData, 
         sizeof (EFI_SATA_CONTROLLER_PRIVATE_DATA), 
         (VOID**)&SataPrivateData 
         );
     if (EFI_ERROR(Status)) { 
     return EFI_OUT_OF_RESOURCES;
      }
      //
      // Initialize SATA private data 
      //
      EfiZeroMem (SataPrivateData, sizeof(EFI_SATA_CONTROLLER_PRIVATE_DATA)); 
      SataPrivateData->Signature = SATA_CONTROLLER_SIGNATURE; 
      SataPrivateData->PciIo = PciIo;
       SataPrivateData->IdeInit.GetChannelInfo = IdeInitGetChannelInfo; 
       SataPrivateData->IdeInit.NotifyPhase = IdeInitNotifyPhase;
       SataPrivateData->IdeInit.SubmitData = IdeInitSubmitData; 
       SataPrivateData->IdeInit.DisqualifyMode = IdeInitDisqualifyMode;
       SataPrivateData->IdeInit.CalculateMode = IdeInitCalculateMode;
       SataPrivateData->IdeInit.SetTiming = IdeInitSetTiming;
       SataPrivateData->IdeInit.EnumAll = ICH_SATA_ENUMER_ALL; 
       SataPrivateData->IdeInit.ChannelCount = ICH_SATA_MAX_CHANNEL; 
       //
       // Enable SATA controller working in appropriate mode 
       //
       Status = EnableSataController (PciIo);
        if (EFI_ERROR(Status)) { 
        return EFI_DEVICE_ERROR; 
        }
        //
        // Install IDE_CONTROLLER_INIT protocol & private data to this instance 
        //
        Status = gBS->InstallMultipleProtocolInterfaces (
                   &Controller, 
                   &gSataControllerDriverGuid,SataPrivateData, 
                   &gEfiIdeControllerInitGuid, &(SataPrivateData->IdeInit), 
                   NULL );

EFI – STOP

EFI_STATUS 
SataControllerStop (
	 IN EFI_DRIVER_BINDING_PROTOCOL *This, 
	 IN EFI_HANDLE Controller, 
	 IN UINTN NumberOfChildren, 
	 IN EFI_HANDLE *ChildHandleBuffer 
	 ) 
	 { EFI_STATUS Status; 
	 EFI_SATA_CONTROLLER_PRIVATE_DATA *SataPrivateData; 
	 Status = gBS->OpenProtocol ( // Open Protocol and Get Private Data 
	                        Controller, 
	                        &gSataControllerDriverGuid, 
	                        (VOID**)&SataPrivateData, 
	                       This->DriverBindingHandle, 
	                        Controller, 
	                        EFI_OPEN_PROTOCOL_GET_PROTOCOL ); 
	 ASSERT_EFI_ERROR (Status);
	 Status = gBS->CloseProtocol ( // Close Protocol 
	                      Controller, 
	                    &gEfiPciIoProtocolGuid, 
	                    This->DriverBindingHandle, Controller 
	    ); 
	    gBS->UninstallMultipleProtocolInterfaces ( // Uninstall Protocol 
	                     Controller, 
	                     &gSataControllerDriverGuid, 
	                     SataPrivateData, 
	                     &gEfiIdeControllerInitGuid, 
	                     &(SataPrivateData->IdeInit), NULL ); 
        gBS->FreePool (SataPrivateData); // Free Private Data
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值