【7】UEFI固件存储格式

主要内容:UEFI 在编译最后会生成一个可以烧进ROM里面的.fd文件。我们下面要了解的是FD是怎么存储的。一个FD(Flash Device binary image),它就是一个二进制镜像文件,其中包含多个FV文件。FV的存储格式是什么样子的?驱动、代码、数据是如何组织在一起,在代码中如何对FV进行发现和修改等操作?

  • 固件FV存储的格式
  • 对FV的访问
    • PEI访问FV
    • DXE访问FV
  • code\data 存储模式
  • EFI IMAGE的格式
  • EFI OPTION ROM格式
  • Variable格式

1. 固件存储的格式


FV是PI规范规定的标准的固件存储格式。

  • FD (Flash Device)

    • 由FV组成
  • FV(Firmware Volume)

    • 代码和数据的基本存储仓库
    • FV是由固件文件系统(FFS(Firmware File System))组织的,并且每个FFS都有自己的属性。
    • 每个Firmware Volume Image包括 Header 和 FFS Image, 还有Free Space。
  • FFS(Firmware File System)

    • 一个FFS(firmware file system)描述在FV 上 Firmware Files 和 Free Space 是如何组织的
    • file GUID 每个固件文件系统都有一个唯一的GUID,该GUID被固件用来将驱动程序与新发现的FV关联起来
    • type 标识FFS的类型,在PEI\PEIM core进行分发时根据type进行查找和分发。
      • EFI_FV_FILETYPE_RAW
      • EFI_FV_FILETYPE_FREEFORM 按照section的方式存储数据比如ACPI table
      • EFI_FV_FILETYPE_PEIM
      • EFI_FV_FILETYPE_DRIVER
      • EFI_FV_FILETYPE_APPLICATION
      • EFI_FV_FILETYPE_SMM
      • EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
  • FS(Firmware Files)

    • 固件卷中具体存储的code和data
    • 属性:Name、Type、Alignment、Size
    • 每个file也有各自的GUID且各不相同
  • section

    • 存放具体的数据
    • section是可以嵌套的
    • type 标识section类型
      • EFI_SECTION_PE32
      • EFI_SECTION_DXE_DEPEX/EFI_SECTION_PEI_DEPEX/EFI_SECTION_SMM_DEPEX
      • EFI_SECTION_USER_INTERFACE
      • EFI_SECTION_RAW
      • EFI_SECTION_FIRMWARE_VOLUME_IMAGE

    每种类型的Section都存储特定的数据。比如PE32类型的Section存储的是代码。而RAW类型的Section则存储包括ACPI Tables这样的纯数据。


2. PEI访问FV


  • FV被认为是线性地址区域
  • 分层的实现FvPpi
    • FvInfoPpi 详细说明了FV镜像的基地址和长度,传递给PEI。
    • PEI中存在一个FvPpi服务,FvPpi有一套标准的服务来访问FV中的段数据。
    • FvHob详细说明了FV镜像的基地址和长度,是PEI和DXE传递数据的方式。

3. DXE访问FV


DXE阶段拿到FV信息后会生成一个FVB 协议,在FVB之上生成一个FV 协议。

通过FVB基于块对flash进行读写,可以对variable进行操作。

  • FV是基础的固件存储的抽象
    • 它是只读的,直到读/写DXE驱动程序把它加载起来
  • 作为分层协议实现
    • Firmware Volume protocol 固件卷协议(固件设备格式摘要)
    • Firmware Volume Block protocol 固件卷块协议(抽象固件设备硬件和分区)
  • FFS (Firmware File System)
    • Space-optimized binary flat format(空间优化的可执行文件格式)

为什么在DXE阶段引入FVB层的概念?

使得数据存储的介质可变,FV提供给上层类似于文件系统的协议,FVB则负责原始数据块写入。这样在更换了下层介质后,FV层不用进行修改,只需要做FVB的适配即可。


3. code/data 存储模式

目的:改数据和代码互不影响。

  • EFI支持的文件系统分区
    • FAT32。文件系统头包含一个GUID,它描述用于组织固件卷数据的固件文件系统的格式。
    • 可插拔的文件系统抽象
  • FV
    • 存储位置和媒介是独立的。(存储的数据可以在其他的存储设备上)
  • 代码和数据的位置不需要在构建时确定
    • Dispatcher和BDS可以使用FV、File或network来查找所需的组件
    • 可以根据平台需求改变封装
  • 举例:对PCI设备驱动程序的加载可以通过OPTION ROM 网络等方式加载。对开机logo的加载存放在fv中,驱动进行访问加载和显示。

4. EFI IMAGE(PE/COFF)


UEFI Images是UEFI定义的、包含可执行代码的一类文件,最显著的特征是包含一个用来定义这段可执行代码格式的PE/COFF header,这个header定义了Processor Type和Image Type。UEFI OS Loader是一种特殊类型的Application。

一个UEFI Image是通过EFI Boot Service gBS->LoadImage()被加载(Load)并重定位(Relocation)到系统内存中的;通过gBS->StartImage()被调用。

  • DOS Header
    • DOS 签名
  • COFF Header
    • 机器类型: IA32 or X64 or ARM
  • Optional Header
    • Section alignment and file alignment(段对齐和文件对齐)
    • Entry point relative address in PE image(入口的相对地址)
    • Subsystem: EFI driver/EFI runtime driver/EFI application(子系统)
    • Data Directory(数据目录)
      • Debug directory to find the debug PDB file path in .rdata section(调试目录,在.rdata部分找到调试PDB文件路径)
      • Relocation directory to find the relocation data in .reloc section(重定向目录,在.reloc节中找到重定向数据)在将efi加载到内存中,对绝对地址进行重定向。
  • Section data
    • .text: the binary instruction code
    • .rdata: the read only data
    • .data: the global data
    • .rsrc: the resource section to include the additional data
    • .reloc: info to reload PE image to the different address

5. EFI OPTIONROM


设备厂商发布设备的UEFI驱动有3种途径:

第一种:与平台BIOS厂商合作,将设备驱动以源码或者二进制的形式包含在UEFI固件中,与UEFI固件一同发布。

第二种:通过UEFI系统分区表(EFI System Partition,ESP)来发布。

第三种:通过PCI Option ROM,将UEFI驱动编译为PCI Option ROM,写入PCI/PCIE板卡设备的存储ROM中,UEFI BIOS将自动加载设备驱动。

Option ROM的特点和格式:

  • option ROM是内置在device中的
  • 在UEFI boot的时候被自动加载
  • EFI Option ROM包含EFI 镜像,作为设备驱动程序
  • ROM 头有0xEF1作为签名
  • PCI数据结构包含了设备ID和供应商ID(哪些设备和哪些供应商是支持的)
  • option rom镜像可能包含不止一个镜像,用来支持不同的平台架构
  • 一般来说,独立的板卡,如网卡、还原卡、物理隔离卡等PCI/PCIE设备,都有自己的ROM芯片,Option Rom代码都存储在ROM芯片中。而板载设备会将Option Rom包在BIOS内以节省成本。
  • UEFI Option ROM实在Legacy Option ROM上发展而来的,在UEFI规范中,它归类在PCI设备驱动中。UEFI Option ROM需要满足UEFI的规范。
  • 在实际运行中,PCI总线驱动必须扫描所有的PCI设备的Option ROM,以判定是否加载。这项工作发生在爱PCI的枚举阶段,PCI总线驱动会寻找设备分类代码(CodeType)为3且标志位是0xEF1的Option ROM。然后检查EFI镜像头结构的子系统值,如果该值设置为11或12(表示启动时服务驱动或运行时服务驱动),那么PCI总线会把Option ROM加载到内存中,作为PCI设备驱动。

6. variable 存储格式


在UEFI架构下,Variable取代了Legacy下的CMOS的功能,用来存放UUID、Setup等的数据。一种数据存储的方式,储存在NVRAM(flash part)或是Memory里,可在Variable的Attribute里设定。

例如设置开机的启动项,设置开机密码等功能.这部分功能在标准的UEFI中都是使用Variable。

VARIABLE:

  • Variable Guid

  • Attribute

    c 复制代码
    ///
    /// Attributes of variable.
    ///
    #define EFI_VARIABLE_NON_VOLATILE        0x00000001
    #define EFI_VARIABLE_BOOTSERVICE_ACCESS  0x00000002
    #define EFI_VARIABLE_RUNTIME_ACCESS      0x00000004
  • UnicodeNameString

  • VariableData

SERVICE & ATTRIBUTE:

Variable Service 是由Runtime Service Table所提供。

  • Read Variable(PEI阶段是只读的)
    • PEI: ReadOnlyVariable2Ppi
    • DXE:VariableArchProtocol
  • Set Variable(只能在DXE(比较后面的时间)和RT阶段修改)
    • DXE VariableWriteArchProtocol is ready(在这个协议ready之后才可写,之前是只读的)
    • EFI_VARIABLE_NON_VOLATILE: Volatile variable doesn't require this attribute.
    • EFI_VARIABLE_BOOTSERVICE_ACCESS: boot time only variable.
    • EFI_VARIABLE_RUNTIME_ACCESS: OS runtime访问变量
  • Variable Reclaim(变量回收)
    • variable写在flash中时。由于flash介质的特性(修改数据需要先擦除再重写,而擦除需要擦除整个块),所以flash上修改数据会重新写数据然后把之前的标注为delete。relaim就是把有效的数据保存然后擦除flash,再把有效数据写回flash。在variable写的比较多的时候就可能会触发此操作。
相关推荐
阿昭L7 天前
调试Windows11启动过程
windows·uefi·windows内核
spencer_tseng8 天前
Thinkpad T440p BIOS F1
bios·thinkpad·f1·t440p
切糕师学AI8 天前
深入理解硬盘分区表(MBR / GPT)与固件启动模式(Legacy / UEFI)
gpt·uefi·mbr·legacy·硬盘分区表·固件启动模式
阿源-9 天前
UEFI Driver 程序框架
嵌入式·uefi
阿源-11 天前
如何在EDKII中编译UNIX风格C语言
嵌入式·uefi·edk2
郭老二15 天前
【经验】工控机上电自启动设置
bios
阿源-23 天前
UEFI Application 如何调用 Protocol
嵌入式·uefi
深念Y25 天前
从CH341A编程器、SPI Flash到Linux+STM32理解
linux·stm32·flash·bios·固件·编程器·闪存
阿源-1 个月前
如何使用 UEFI Shell 执行 Hello World 程序
uefi·edk2