当前位置: 代码迷 >> 综合 >> UEFI 设计精髓
  详细解决方案

UEFI 设计精髓

热度:66   发布时间:2023-12-14 22:28:29.0

大到一个国家,小到一个家庭,如果要有序发展,其中最重要的事情,就是个体之相相互沟通。人与人之间,可以通过发微信,skype , 沟通,那个数百万行的UEFI BIOS 是如何沟通的呢?

在UEFI 里面,最重要两个阶段,就是pei 和dxe, 其中PEIM之间信息沟通,主要是通过PPI, DXE Driver 之间信息沟通主要是通过protocol. 

具体来说,对于DXE阶段, 一个Handle 上安装有一个或多个protocol 的具体实现(Interface). 针对

某个特定protocol, 一个handle 上只允许安装一个对应的接口。安装的操作通过 InstallMultipleProtocolInterfaces(), InstallProtocolInterface() 完成。从handle 上卸载Interface 的操作通过UninstallMultipleProtocolInterfaces(), UninstallProtocolInterface() 完成。通过HandleProtocl() 可以查询指定的handle 上是否安装有特定的protocol的interface. 通过LocateHandle()、 LocateHandleBuffer() 可以查询系统中安装特定protocol 的handle list. 通过这些接口,我们实现了驱动A 安装某个特定的protocol interface. 驱动B查询并使用该interface 

注 interface 就是函数!!

 

 PPI 和 Protocol 都可以install, 都可以locate, 那么它们的差别是什么? 为什么不用同一套统一的方案去做呢?

 

首先,PEI 主要是在FLASH 上面运行的,应该设计得尽可能简单,快速。

 

说明一下, 同一个guid 也可以对应多个instance. 因为在locate PPI 的时候,可以传入不同的instance, 得到具体想要的那一个interface .

 

/**This function locates an interface in the PEI PPI database by GUID.@param  PeiServices      An indirect pointer to the EFI_PEI_SERVICES published by the PEI Foundation.@param  Guid             A pointer to the GUID whose corresponding interface needs to be found.@param  Instance         The N-th instance of the interface that is required.@param  PpiDescriptor    A pointer to instance of the EFI_PEI_PPI_DESCRIPTOR.@param  Ppi              A pointer to the instance of the interface.@retval EFI_SUCCESS           The interface was successfully returned.@retval EFI_NOT_FOUND         The PPI descriptor is not found in the database.**/
typedef
EFI_STATUS
(EFIAPI *EFI_PEI_LOCATE_PPI)(IN CONST EFI_PEI_SERVICES            **PeiServices,IN CONST EFI_GUID                    *Guid,IN UINTN                             Instance,IN OUT   EFI_PEI_PPI_DESCRIPTOR      **PpiDescriptor OPTIONAL,IN OUT   VOID                        **Ppi);

 

而到了DXE 阶段,我们引入了HANDLE 的概念,一个handle 通过install protocol 挂了很多个protocol. 不同的handle 上面同一个guid 对应的protocol 可以有着不同的instance (实现)

再则,我们引入devicepath 的概念,这样在构建driver 的时候,不同的devicepath 所需要的protocol 可以有着不同的实现 。而且在用的时候,只需要定位(locate) 到这个handle 就行。 这里跟C++ 的多态的设计理念高度一致。

 

众所周知,bios 的主要功能是把主板上的各种device 驱动起来,所以bios 里面要实现各种device的驱动,而为了让驱动设计更简洁,一致,我们为所有驱动提供了一个模型,大家都按这个框架去做。

已知这个模型(driver  binding model) 有support , start  stop, 在support 的时候,我们就是拿devicepath 去看这个driver 是否support 这个driver . 而start 因为有着不同的devicepath , 所以start 可能会被多次调用到。

 

举例:

在BDS 的时候,去connect 一个U盘,假设它的device path 如下:

pci/usbbus/usbport/u盘

在第一轮,可以先把pci 的driver start 起来,

在第二轮,可以找到 usbbus 的driver ,并把它start起来,... 依此类推, 最后找到usb mass storage driver ,并 start 起来。

由此构建出u盘的driver (stack).

 

结论:

在DXE 阶段,我们引入handle, device path 这两个概念,我们就可以构建出各种复杂的驱动。