目录
支持的体系结构
体系结构可以是 IA32、X64、IPF、EBC、Mips、ARM 中的一个.
MdeModulePkg
这个包提供符合 UEFI/PI 行业标准的模块,还提供用于这些模块的定义(包括 PPI/Protocol/Guids 和 Library 类)和库实例。
Application/ Bus/ Core/ Include/ Library/ Logo/ Universal/ |
MdeModulePkg.dec MdeModulePkg.dsc MdeModulePkgExtra.uni MdeModulePkg.uni |
MdePkg
Include/ | Arm/ Ebc/ Ia32/ Ipf/ Mips/ X64/ AArch64/ Guid/ IndustryStandard/ Library/ Pi/ Protocol/ Ppi/ Uefi/ Base.h Base.h PiMm.h PiSmm.h PiMm.h PiSmm.h PiMm.h PiSmm.h |
Library/ | Base**/ Dxe**/ Pei**/ Smm**/ Uef**/ |
MdePkg.dec MdePkg.dsc MdePkgExtra.uni MdePkg.uni |
模块开发环境包(MdePkg)是一个特殊的包,因为它是构建模块所需的最小基础设施。模块可能需要额外的包构建,但所有模块都基于 MdePkg。通过保持 MdePkg 非常稳定,它有效地成为一个模块或设备驱动程序工具包,用于构建可以与各种包一起工作的模块。
mdepkg 提供了所有定义(包括函数、宏、结构和库类)和库实例,这些在 mdepkg 中定义。最新的 mdepkg.chm 文件将记录这些定义,并可以在最新的udk发布中找到。
它还提供了 eFi1.10/uefi2.x/pi1.x 和其他行业标准的定义(包括 PPIS/协议/guids)。
mdepkg 支持构建一系列模块类型。mdepkg 可以单独使用,也可以与其他包结合使用来生成模块。 mdepkg 可以生成独立的模块,定义为只使用 mdepkg 中定义的类型为 BASE 的资源的 BASE。基本模块允许您编写可移植的 C 代码,这些 C 代码可以很容易地移植到任何环境中。mdepkg 可以用 C 代码来编写 SEC。mdepkg 包还可以生成符合 EFI1.10或 UEFI2.x 规范的 UEFI 驱动程序或 UEFI 应用程序。MDEFKG 还可以基于EDK II构建环境描述在EDK II 规格.
文件解析
*pkg | 模块 | 原数据文件(.inf文件) 原文件(.efi文件组成) | ![]() | |
dsc文件 | 用来编译一个Package | [Defines]:设置build相关的全局宏变量。这些变量要被.dsc文件的其他模块所引用 [LibraryClasses]:定义库的名字,以及库中的.inf文件,能够被其他模块所引用 [Components]:该区块内定义的模块会被build命令编译成对应的.efi文件 [BuildOptions]:列出本模块编译源文件时用到的编译选项,对所有模块的文件都有效 [PCD]:用于定义平台配置数据,目的在于不改动.inf文件和源文件的情况下完成对平台的配置。 | ||
.dec文件 | 主要定义公开的数据和接口供其他模块使用 | [Definces]:用于提供Package的名称,GUID和版本号等信息。 [Includes]:列出了Package所提供的头文件所在的目录。 [LibraryClasses]:用于明确库和头文件的对应关系。 [Guids]:Package/Include/Guid目录下面有很多文件,每个文件中定义了GUID号,这些号会被复制到对应的AutoGen.c中。 [Protocols]:Package/Include/Protocols目录下面有很多文件,每个文件中定义了Protocols号。 [Ppis]:用于定义源文件中用到的PPI(PPI是PEI阶段PEI模块之间的通信接口) [PCD]:是.dsc文件中PCD块的补充。 [UserExtenssions]: |
每个模块是如何被编译城.efi文件的
- 编译器将源文件编译成.obj文件
- 链接器将.obj文件和其他使用的库文件生成.dll文件
- GenFw工具将.dll文件转换成.efi文件
- GenFd命令将.efi文件最终生成.fd文件
AutoGen.c和AutoGen.h和如何生成的
- 执行./build 命令后,解析模块的.inf文件然后生成AutoGen.c和AutoGen.h
标准应用程序模块执行的过程
- 将标准应用程序模块对应的.efi文件加载到内存,找到对应的StartImage文件
- 然后进入函数_ModuleEntryPoint函数
- 然后进入ProcessModuleEntryPointList
- 然后进入对应的模块的入口函数
_ModuleEntryPoint函数的主要作用
- 初始化:初始化一些列的构造函数
- 调用本模块的入口函数
- 析构(执行解析构造函数)
完整的驱动程序的框架
- FindOut()找出对应的硬件设备
- Install()/Start()安装驱动到指定的设备控制器
- Uninstall/Stop()从硬件设备上卸载驱动
UEFI驱动模型
- UEFI驱动模型的核心是通过EFI Driver Binding Protocol来管理驱动程序。
- 完整的驱动程序包含两部分:EFI Driver Binding Protocol和驱动程序本身
UEFI加载驱动的整个过程
- 首先在Shell命令下使用load命令将驱动文件加载到内存,加载后UEFI后调用gBS->StartImage(...)执行DriverImage的入口函数,在入口函数里,Driver Binding Protocol被加载
- 到Handle(Driver Image Handle或者其他Controler Handle)上。然后遍历所有控制器为每个控制器调用CoreConnectSingleController函数,在CoreConnectSingleController中调用EDBP的Support函数测试是否支持这个驱动,如果支持责调用Start()函数进行安装。
编写UEFI驱动的步骤
- 编写硬件相关部分的驱动程序(驱动本身)
- 驱动框架部分,实现Driver Binding Protocol 的三个接口函数Supported() Start() Stop()函数
Supported()函数要点
- 忽略参数RemainingDeivePath
- 使用函数OpenProtocol()函数打开所需要的Protocol。标准的驱动要用EFI_OPEN_PROTOCOL_BY_DRIVER属性打开,如果要独占某个Protocol需要关闭所有使用该Protocol的驱动程序。然后用属性EFI_OPEN_PROTOCOL_BY_DRIVER|EFI_OPEN_PROTOCOL_EXCLUSIVE打开Protocol
- 如果上面出错,调用CloseProtocol()关闭所有已经打开的Protocol并返回错误码。
- 所需要的Protocol成功打开后,测试这个driver是否支持这个Controler,如果任意一项测试失败,调用CloseProtocol()函数挂比所有打开的Protocol,并返回EFI_UNSUPPORTED
- 测试成功,调用CloseProtocol()关闭所有已打开的Protocol
- 返回EFI_SUCCESS
Start()函数要点
- 忽略参数RemainingDeivePath
- 使用函数OpenProtocol()函数打开所需要的Protocol。标准的驱动要用EFI_OPEN_PROTOCOL_BY_DRIVER属性打开,如果要独占某个Protocol需要关闭所有使用该Protocol的驱动程序。然后用属性EFI_OPEN_PROTOCOL_BY_DRIVER|EFI_OPEN_PROTOCOL_EXCLUSIVE打开Protocol
- 如果上面出错,调用CloseProtocol()关闭所有已经打开的Protocol并返回错误码。
- 初始化Controler所指定的设备,如果有错误,则关闭所有打开的Protocol,返回EFI_DEVICE_ERROR
- 分配并初始化所用到的数据结构,数据结构包含Protocol相关的数据结构和其他 的私有的数据结构。如果分配资源的时候发生错误,就关闭所有已经打开的Protocol,释放已经得到的资源,EFI_OUT_OF_RESOURCE
- 用InstallMultipleProtocolInterface()安装驱动协议到 ControlerHandle,如果有错误,关闭所有打开的Protocol,并返回错误码
- 返回EFI_SUCCESS
Stop()函数要点
- 用UnInstallMultipleProtocolInterface()函数卸载所安装的Protocol
- 关闭所有已经打开的Protocol。
- 释放所有申请的资源