UEFI开发学习 30 – UEFI 固件拆解
我们只需执行一个简单的 Build 命令,即可完成一个 UEFI 固件的构建。UEFI固件内部是如何组成的呢?本文将讨论UEFI固件的组织方式。
从 FV 到 FD
我们最终在芯片上烧录的固件镜像,通常被称为 FD (Firmware Device) 文件。可以把它想象成一个完整的硬盘镜像,是固件在物理存储介质(如 SPI Flash)上的最终形态。
一个 FD 文件的内部由一个或多个 FV (Firmware Volume) 组成。FV 是 UEFI 固件中的逻辑存储单元,类似于磁盘上的分区。每个 FV 都有自己的头部信息(FV Header),其中定义了这个 FV 的大小、属性以及它内部文件的组织格式。
这种分区设计带来了极大的灵活性。例如,一个 FD 中可以包含一个用于存储启动关键驱动(DXE)的主 FV,还可以包含一个独立的可变存储 FV(用于保存 NVRAM 变量),甚至一个用于恢复的备份 FV。
从 FFS 到 FV
FV (Firmware Volume) 的主要作用是作为 FFS (Firmware File System) 文件的容器。FFS 是 UEFI 定义的一种文件系统,专门用于在 FV 中组织和存储固件模块。
每个 FV 内部都包含了一系列 FFS 文件。FV 的头部信息之后紧跟着就是一个个 FFS 文件,它们依次排列,直到 FV 的末尾。FV 通过一套机制来索引和定位这些 FFS 文件。
每个 FFS 文件都由两部分组成:
FFS Header:头部信息,用于描述这个文件。
FFS Section(s):文件体,包含实际的数据。
FFS Header 中最重要的信息是它的 GUID。这个 GUID 是每个 FFS 文件的唯一标识符,UEFI 的各个启动阶段(如 PEI 和 DXE)就是通过 GUID 来查找并加载所需要的模块。
从 EFI 到 FFS
FFS 文件通过其内部的 Section 来承载数据。一个 FFS 文件可以包含一个或多个 Section。其中,最常见的 Section 类型就是 EFI_SECTION_PE32,它的内容就是一个标准的 PE32/PE32+ 格式的可执行文件——也就是我们所说的 EFI 文件。
除了 EFI_SECTION_PE32,还有其他类型的 Section,例如:
EFI_SECTION_COMPRESSION:表示其内部的数据是经过压缩的,加载时需要先解压。
EFI_SECTION_USER_INTERFACE:包含可供用户查看的字符串,通常是这个模块的名称。
EFI_SECTION_VERSION:包含模块的版本号。
通过将 EFI 文件封装在 FFS 文件中,固件可以附加额外的元数据(如 GUID、版本、描述等),并利用 FV 的文件系统来管理这些可执行模块。
EFI 构成
无论是 UEFI 驱动、应用程序(如 UEFI Shell),还是 UEFI 启动加载器(Bootloader),它们本质上都是 EFI 文件。
EFI 文件遵循微软定义的 PE/COFF (Portable Executable / Common Object File Format) 格式,这与 Windows 系统下的 .exe 和 .dll 文件格式是相同的。
DOS Header:历史遗留部分,主要为了兼容 MS-DOS。
COFF File Header:包含文件的基本信息,如目标平台(x86, x64, ARM)、Section 的数量等。
Optional Header:这是 PE 格式的核心。对于 UEFI 来说,其中最重要的字段是 Subsystem。这个字段的值决定了该 EFI 文件是一个应用程序(EFI_APPLICATION)、一个启动服务驱动(EFI_BOOT_SERVICE_DRIVER),还是一个运行时驱动(EFI_RUNTIME_DRIVER)。链接器根据源代码的入口点类型(如 UefiMain)来设置这个值。
Section Table:段表,描述了文件中所有 Section 的信息,如名称、大小、内存中的位置和属性(可读、可写、可执行)。
Sections:真正的代码和数据存放在这里。常见的 Section 包括:
.text:存放编译后的可执行代码。
.rdata:存放只读数据,例如常量字符串。
.data:存放已初始化的全局变量和静态变量。
.reloc:存放重定位信息。由于 UEFI 程序加载到内存的地址可能不是预设的基地址,需要根据 .reloc 信息来修正代码和数据中的绝对地址引用。
Terse Image (TE) 格式
为了节省在固件存储芯片中的空间,UEFI 定义了一种更为紧凑的镜像格式,称为 Terse Image (TE)。TE 镜像通过一个精简的 TE Header 替换了标准的 DOS Header、Optional Header,从而显著减小了文件头部的大小。
总结
FD 是物理存储介质上的完整镜像。
FD 由一个或多个 FV 组成,FV 如同分区。
FV 是一个文件系统,容纳着许多 FFS 文件。
FFS 是一个包装器,通过 GUID 来标识,其核心内容通常是一个 EFI 文件。
EFI 是一个 PE/COFF 格式的可执行文件,是实现所有 UEFI 逻辑(驱动、应用)的最终载体。
版权声明:
作者:bin
链接:https://ay123.net/mystudy/1874/
来源:爱影博客
文章版权归作者所有,未经允许请勿转载。

共有 0 条评论