UEFI 概要

本文深入探讨UEFI驱动开发流程,解析MdeModulePkg和MdePkg的作用,介绍模块编译成.efi文件的方法,AutoGen.c和AutoGen.h的生成过程,以及标准应用程序模块的执行流程。详细讲解了_ModuleEntryPoint函数的功能,展示了完整驱动框架和UEFI驱动模型,最后详述了UEFI驱动加载全过程及编写步骤。

目录

支持的体系结构

MdeModulePkg

MdePkg

文件解析

每个模块是如何被编译城.efi文件的

AutoGen.c和AutoGen.h和如何生成的

标准应用程序模块执行的过程

_ModuleEntryPoint函数的主要作用

完整的驱动程序的框架

UEFI驱动模型

UEFI加载驱动的整个过程

编写UEFI驱动的步骤

Supported()函数要点

Start()函数要点

Stop()函数要点


支持的体系结构

体系结构可以是 IA32、X64、IPFEBC、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文件的

  1. 编译器将源文件编译成.obj文件
  2. 链接器将.obj文件和其他使用的库文件生成.dll文件
  3. GenFw工具将.dll文件转换成.efi文件
  4. GenFd命令将.efi文件最终生成.fd文件

 

AutoGen.c和AutoGen.h和如何生成的

  • 执行./build 命令后,解析模块的.inf文件然后生成AutoGen.c和AutoGen.h

 

标准应用程序模块执行的过程

  1. 将标准应用程序模块对应的.efi文件加载到内存,找到对应的StartImage文件
  2. 然后进入函数_ModuleEntryPoint函数
  3. 然后进入ProcessModuleEntryPointList
  4. 然后进入对应的模块的入口函数

 

_ModuleEntryPoint函数的主要作用

  • 初始化:初始化一些列的构造函数
  • 调用本模块的入口函数
  • 析构(执行解析构造函数)

 

完整的驱动程序的框架

  1. FindOut()找出对应的硬件设备
  2. Install()/Start()安装驱动到指定的设备控制器
  3. Uninstall/Stop()从硬件设备上卸载驱动


UEFI驱动模型

  • UEFI驱动模型的核心是通过EFI Driver Binding Protocol来管理驱动程序。
  • 完整的驱动程序包含两部分:EFI Driver Binding Protocol和驱动程序本身


UEFI加载驱动的整个过程

  1. 首先在Shell命令下使用load命令将驱动文件加载到内存,加载后UEFI后调用gBS->StartImage(...)执行DriverImage的入口函数,在入口函数里,Driver Binding Protocol被加载
  2. 到Handle(Driver Image Handle或者其他Controler Handle)上。然后遍历所有控制器为每个控制器调用CoreConnectSingleController函数,在CoreConnectSingleController中调用EDBP的Support函数测试是否支持这个驱动,如果支持责调用Start()函数进行安装。


编写UEFI驱动的步骤

  1. 编写硬件相关部分的驱动程序(驱动本身)
  2. 驱动框架部分,实现Driver Binding Protocol 的三个接口函数Supported() Start() Stop()函数

Supported()函数要点

  1. 忽略参数RemainingDeivePath
  2. 使用函数OpenProtocol()函数打开所需要的Protocol。标准的驱动要用EFI_OPEN_PROTOCOL_BY_DRIVER属性打开,如果要独占某个Protocol需要关闭所有使用该Protocol的驱动程序。然后用属性EFI_OPEN_PROTOCOL_BY_DRIVER|EFI_OPEN_PROTOCOL_EXCLUSIVE打开Protocol
  3. 如果上面出错,调用CloseProtocol()关闭所有已经打开的Protocol并返回错误码。
  4. 所需要的Protocol成功打开后,测试这个driver是否支持这个Controler,如果任意一项测试失败,调用CloseProtocol()函数挂比所有打开的Protocol,并返回EFI_UNSUPPORTED
  5. 测试成功,调用CloseProtocol()关闭所有已打开的Protocol
  6. 返回EFI_SUCCESS


Start()函数要点

  1. 忽略参数RemainingDeivePath
  2. 使用函数OpenProtocol()函数打开所需要的Protocol。标准的驱动要用EFI_OPEN_PROTOCOL_BY_DRIVER属性打开,如果要独占某个Protocol需要关闭所有使用该Protocol的驱动程序。然后用属性EFI_OPEN_PROTOCOL_BY_DRIVER|EFI_OPEN_PROTOCOL_EXCLUSIVE打开Protocol
  3. 如果上面出错,调用CloseProtocol()关闭所有已经打开的Protocol并返回错误码。
  4. 初始化Controler所指定的设备,如果有错误,则关闭所有打开的Protocol,返回EFI_DEVICE_ERROR
  5. 分配并初始化所用到的数据结构,数据结构包含Protocol相关的数据结构和其他 的私有的数据结构。如果分配资源的时候发生错误,就关闭所有已经打开的Protocol,释放已经得到的资源,EFI_OUT_OF_RESOURCE
  6. 用InstallMultipleProtocolInterface()安装驱动协议到 ControlerHandle,如果有错误,关闭所有打开的Protocol,并返回错误码
  7. 返回EFI_SUCCESS


Stop()函数要点

  1. 用UnInstallMultipleProtocolInterface()函数卸载所安装的Protocol
  2. 关闭所有已经打开的Protocol。
  3. 释放所有申请的资源

 

 

<think>嗯,用户这次想了解UEFI Shell界面的详细说明。从提供的参考资料来看,用户已经查阅过一些关于UEFI Shell命令和工具的文章,包括常用命令整理、变量操作命令、截屏工具等。 用户可能正在学习UEFI开发或系统维护,需要深入理解Shell环境的工作方式。考虑到用户引用的资料比较零散,我需要整合这些信息,构建一个完整的Shell界面说明框架。 注意到引用[1]提到UEFI Shell Specification是权威文档,但用户似乎希望获得中文的概要说明。引用[2]详细介绍了variables命令的参数使用,这说明用户对具体命令实现细节有兴趣。引用[3][4]则显示用户关注Shell下的扩展功能(如截屏)和部署方式。 在组织回答时,应该突出几个核心维度:Shell的定位作用、交互特征、核心功能层级、典型使用场景。特别要注意引用[4]提到的启动方式差异,不同平台进入Shell的方式可能不同,这点对实操很重要。 用户引用的materials里藏着不少关键细节:比如variables命令的-guid参数默认值、NV变量的定义,这些都应该融入说明中。不过用户明确要的是"界面说明",所以重点放在交互逻辑上,命令细节只需举例。 最后生成的问题要引导用户深入:既然用户研究了基础界面,接下来可能会关心调试技巧或定制开发,所以问题设计从脚本编写、调试应用到定制扩展层层递进比较合适。 </think>好的,以下是关于UEFI Shell界面的详细说明: UEFI Shell(统一可扩展固件接口 Shell)是一个运行在UEFI固件环境之上的命令行界面。它为用户和开发者提供了在操作系统启动前访问硬件、管理固件设置、运行诊断程序以及执行脚本的强大能力。 **UEFI Shell界面的核心要素和详细说明:** 1. **启动与进入方式:** * 启动方式因设备而异: * **主板内置:** 某些主板开机时按特定键(如 F2, F8, F12, Del 等,具体需查阅主板手册)“启动菜单”或“Boot Option Menu”中可能包含直接启动UEFI Shell的选项。 * **外部Shell:** 更常见的方式是将UEFI Shell的EFI应用程序(通常名为 `Shell.efi` 或 `Shellx64.efi`)放置在ESP(EFI系统分区)的某个路径下(如 `\EFI\Boot\` 或自定义目录)。然后在UEFI固件设置(Setup)的启动选项(Boot Options)中将其添加为一个启动项,或者从启动菜单选择该Shell启动项[^4]。 * 启动成功后,会加载Shell应用并显示命令行提示符。 2. **命令行提示符:** * 典型的UEFI Shell提示符格式为:`Shell> ` 或 `FSX:\> `。 * `Shell>` 通常表示当前工作目录位于映射的某个文件系统设备的根目录下。 * `FSX:\>` 表示当前工作目录在映射号为 `FSX` 的文件系统设备上(如 `FS0:\>` 表示映射到第一个找到的ESP分区)。 3. **映射文件系统(Map):** * UEFI Shell的核心功能之一是访问存储设备上的文件系统(主要是FAT格式,ESP必须为FAT)。 * 使用 `map` 命令列出所有被识别并映射的设备: * **`BlkX`:** 块设备(Block Device),通常代表物理磁盘或分区,但未加载文件系统驱动。 * **`FSX`:** 文件系统设备(File System Device),代表已成功加载文件系统驱动并识别了文件系统的分区(如ESP)。这是你可以使用 `cd`、`ls`、`edit` 等命令操作目录和文件的地方。 * **输出示例:** ```bash Shell> map Mapping table FS0: Alias(s):HD0a0a0:; BLK1: PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x0,0x0)/HD(1,GPT,E6E6F...) ``` * **切换目录 (`cd`) 和列出文件 (`ls`/`dir`):** ```bash Shell> fs0: # 切换到文件系统设备FS0 FS0:\> cd EFI # 进入EFI目录 FS0:\EFI> ls # 列出EFI目录下的内容 ``` * **文件操作:** 支持基本的文件操作命令如 `cp` (复制), `mv` (移动/重命名), `rm` (删除), `edit` (文本编辑器) 等。 4. **命令结构和参数:** * 命令格式一般为:`CommandName [Options] [Arguments]` * **选项 (`Options`):** 通常以 `-` 或 `/` 开头(不同命令可能有惯例),用于修改命令行为。例如: * `ls -b`:列出文件时包含文件大小信息。 * `dmpstore -all`:显示所有UEFI变量(`dmpstore`是显示变量的常用命令)。 * `variables -guid 8BE4DF61-93CA-11D2-AA0D-00E098032B8C`:显示特定GUID下的变量(引用[2]中提到`-guid`参数及其默认值)[^2]。 * **参数 (`Arguments`):** 命令操作的对象,如文件名、路径、设备名、变量名等。 * **获取帮助:** 大部分命令支持 `-?` 或 `/?` 选项来显示该命令的帮助信息。例如:`help -b`, `dmpstore -?`。 5. **核心功能区域:** * **系统和固件信息:** 命令如 `smbiosview` (查看SMBIOS表), `dmem` (显示内存内容), `cpuid` (显示CPU信息), `drivers` (列出加载的驱动), `dh` (显示设备句柄) 等。 * **UEFI变量管理:** (极其重要)命令如: * `dmpstore`:显示UEFI变量(类似于引用[2]中的功能)。 * `setvar`:设置UEFI变量(需要管理员权限,风险高)。 * UEFI变量有不同类型(Boot Service/BS, Runtime Service/RT)和属性(易失性/Volatile, 非易失性/NV),如引用[2]中 `variables` 命令的 `-bs`, `-rt`, `-nv` 选项所示[^2]。 * **设备管理:** `connect` (连接驱动和设备), `disconnect` (断开连接), `devices` (列出设备), `drvcfg` (配置驱动) 等。 * **网络功能(如果支持):** `ifconfig` (配置网络接口), `ping` (网络连通性测试), `ipconfig` (有时也用于显示配置)。需要加载网络驱动(`.nii`)。 * **引导管理:** `bcfg` (管理启动项), `boot` (引导操作系统或应用程序)。`bcfg` 是管理UEFI启动菜单(`BootXXXX` 变量)的主要工具。 * **脚本执行:** Shell支持执行脚本(`.nsh` 文件),允许批量执行命令,自动化任务。引用[1]提到提供了脚本参考[^1]。 * **实用工具:** 如 `reset` (重启系统), `mode` (设置屏幕显示模式), `vol` (显示卷信息),以及如引用[3]提到的截屏工具(需要额外加载)[^3]等。 6. **Shell环境特性:** * **预操作系统环境:** 在OS Loader之前运行,独立于任何操作系统。 * **访问底层硬件和固件:** 提供了直接与UEFI服务和硬件交互的能力,用于调试、恢复、固件更新等。 * **可扩展性:** 可以通过加载额外的 `.efi` 应用程序(如引用[3]的截屏工具[^3])或驱动(如网络驱动 `.nii`)来扩展功能。 * **标准化命令行:** 遵循 UEFI Shell Specification(引用[1]提到的文档[^1]),确保不同厂商实现的基本一致性。 **总结:** UEFI Shell界面是一个强大的命令行环境,其核心在于通过 `map` 访问文件系统、使用丰富的内置命令查询管理固件信息(特别是UEFI变量)、操作系统启动项、硬件设备,并可运行脚本和扩展程序。它是在操作系统启动前进行系统维护、调试、恢复和定制化操作的关键工具。用户的操作主要集中在映射的文件系统设备(`FSX:\>`)下浏览文件、执行命令和脚本。熟练掌握常用命令(如 `map`, `ls`, `cd`, `dmpstore`, `bcfg`, `reset` 等)及其选项是有效使用Shell的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值