UEFI中的edk2编译流程_edk2代码走读

GenFds(Generate Firmware Descriptor)用于生成描述固件映像的描述符文件(通常具有.fd扩展名)。这些描述符文件包含有关UEFI固件映像的信息,包括Firmware Volume(FV)的信息、Firmware File System(FFS)文件的信息以及其他与UEFI固件相关的元数据。

Image

Image指的是映像文件,一般指可执行的二进制文件或固件文件。

生成FFS文件
  • a. GenFfs工具: 生成的TE格式文件通常会被打包成FFS文件。GenFfs工具是用于这一目的的工具之一。GenFfs工具会读取一个FDF文件(Flash Description File),该文件描述了FFS文件的组织结构和内容。
  • b. FFS容器: GenFfs工具将TE文件打包到FFS容器中,为每个FFS文件创建一个FFS标头。FFS标头包含有关FFS文件的元数据,例如文件类型、大小和属性。
生成FV文件
  • a. GenFv工具: 在构建过程的某个阶段,通常是在post-build阶段的后期,使用GenFv工具或类似的工具来创建FV(Firmware Volume)文件。FV文件是一种UEFI特定的容器,可以包含一个或多个FFS文件。
  • b. FV标头: GenFv工具为FV文件添加一个FV标头,其中包含有关FV的元数据,如文件系统信息、校验和等。
生成FD文件

GenFds(Generate Firmware Descriptor)工具是EDK II的一部分,用于生成Firmware Volume(FV)描述符文件,其中包含有关UEFI固件中包含的FV的信息。这些描述符文件通常具有.fd文件扩展名。可以使用GenFds工具创建描述符文件,其中包含一个或多个FV的信息。这对于将多个FV嵌入到UEFI固件中非常有用。

FD、FV、FFS

UEFI中的FD(Firmware Device)、FV(Firmware Volume)和FFS(Firmware File System)可以被看作是一种层次结构,类似于树状图的结构,其中FD是根,FV是树的分支,而FFS是树的叶子。这种层次结构有助于组织和管理UEFI固件中的各种数据和文件。

在UEFI中,FD、FV和FFS是固件开发中常见的概念,它们分别表示固件设备(Firmware Device)、固件卷(Firmware Volume)和固件文件系统(Firmware File System)。它们之间有以下区别和联系:

  1. FD(Firmware Device):FD是UEFI固件的最高级别概念,它代表了整个固件设备,包括固件芯片或存储器。FD文件是UEFI固件的核心部分,包含了引导程序、驱动程序和其他必要的固件组件。FD文件是UEFI固件的主要执行部分,负责启动和初始化硬件设备。
  2. FV(Firmware Volume):FV是UEFI固件中的一种数据结构,用于组织和存储固件的各个部分。一个FV可以包含多个模块(Module),每个模块可以是一个驱动程序、一个应用程序或其他固件组件。FV文件相当于UEFI固件的存储空间,它通过GUID(全局唯一标识符)来标识和访问其中的模块。
  3. FFS(Firmware File System):FFS是UEFI固件中的一种文件系统,用于组织和管理固件中的文件。FFS由一个或多个文件组成,每个文件都有唯一的GUID标识符。FFS文件可以存储各种类型的数据,包括驱动程序、配置文件、固件升级文件等。FFS文件系统是FV中的一个重要组成部分,它提供了对固件中文件的访问和管理功能。

区别和联系:

  • FD是UEFI固件的最高级别概念,代表整个固件设备;FV是UEFI固件中的数据结构,用于组织和存储固件的各个部分;FFS是UEFI固件中的文件系统,用于组织和管理固件中的文件。
  • FD文件是UEFI固件的核心部分,包含引导程序、驱动程序等;FV文件是UEFI固件的存储空间,包含多个模块;FFS文件是FV中的一个重要组成部分,用于存储各种类型的数据。
  • FD文件包含了FV文件;FV文件包含了FFS文件;FFS文件存储在FV文件中。它们之间存在依赖关系,共同构成了UEFI固件的结构和功能。

FD与FV

在UEFI中,FD(Firmware Device)和FV(Firmware Volume)之间存在着一种父子关系。

FD文件是UEFI固件的核心部分,它包含了UEFI固件的引导程序、驱动程序和其他必要的固件组件。FD文件会将FV文件加载到内存中,并通过FV文件中的模块来执行相应的功能。

FV文件是UEFI固件中的一种数据结构,用于组织和存储固件的各个部分。一个FD可以包含多个FV,每个FV可以包含多个模块。FV文件通过GUID(全局唯一标识符)来标识和访问其中的模块。

因此,可以说FV文件是FD文件中存储固件组件的一种方式,FD文件通过加载FV文件来实现固件的功能。FD和FV之间的关系可以理解为父子关系,FD是FV的上层容器,FV是FD中存储固件组件的一种结构。

FV与FFS

FFS虽然是一个文件系统,但是它并没有层次结构,所有的固件文件都一字排开,组成固件文件系统。这种结构也就导致,查询某一个固件文件只能够遍历。

FFS Header

FFS的头包含了部分属性,Name、Type、State、Size

Section Header

Section的头包含了Section的Type与Length

Section与efi

在UEFI(统一可扩展固件接口)中,“section”(节)是一个术语,通常指的是可执行二进制文件(例如.efi文件)中的逻辑分块或段。每个节包含了特定类型的数据或代码,用于实现特定的功能。这些节被组合在一起构成一个完整的可执行文件。

一个EFI可执行文件(例如.efi文件)通常包含多个节,每个节有其特定的功能和数据。以下是一些常见的EFI可执行文件中可能包含的节:

  1. 代码节(Code Section):这些节包含可执行代码,用于执行特定的任务。例如,一个EFI引导加载程序的代码节包含引导加载程序的实际执行代码。

  2. 数据节(Data Section):这些节包含各种数据,如全局变量、常量数据等。数据节可以存储用于在程序执行过程中读取或修改的数据。

  3. 引导信息节(Boot Information Section):这些节包含关于EFI映像的元数据和信息,如映像的版本、作者、创建日期等。这些信息通常不是必需的,但可以用于描述EFI映像的属性。

  4. 调试信息节(Debug Information Section):这些节包含用于调试的信息,例如源代码行号和变量名的映射。调试信息节对于开发人员在调试EFI映像时非常有用。

  5. 导出节(Export Section):这些节包含了EFI映像提供给其他EFI模块或应用程序使用的接口信息。这些接口可以被其他模块引用,以实现模块间的通信和交互。

这些节的组合构成了一个完整的EFI可执行文件。每个节都有其自己的特定用途,它们共同协作以实现EFI应用程序或驱动程序的功能。EFI标准规定了EFI可执行文件的格式和节的结构,以确保它们在UEFI环境中能够正确加载和执行。所以,“section” 是EFI可执行文件中的逻辑组成部分,用于实现不同的功能。

Section

Section有很多种类型,但是总的来说其实就两种:封装节(En)、叶子节(Ln),而一个固件文件中的Section分布可以如下图,可以既有封装节,也可以有叶子节,而封装节类似于父节,它可以包含作为子节的封装节与叶子节。

VTF

卷顶文件(VTF)是必须定位的文件,该文件的最后一个字节也是固件卷的最后一个字节。VTF的文件名GUID为EFI_FFS_VOLUME_TOP_FILE_GUID,固件文件系统驱动程序代码必须知道这个GUID,并根据需要插入一个pad文件,以保证在写入和更新操作时VTF正确地位于固件卷的顶部。文件长度和对齐要求必须与卷顶一致。否则,写错误,不修改固件卷。

FDF

FDF文件用于描述固件在flash中的布局和位置,这些固件是与UEFI兼容的二进制镜像,一般来说,生成固件的源码中只有一个FDF文件,其作用是规定把哪些包编入flash中,并确定编入的位置,FDF文件由[Defines]、[FD]、[FV]、[Capsule]、[VTF]、[Rule]、[OptionRom]组成。下面以edk2下的EmulatorPkg下的EmulatorPkg.fdf文件为例。

[FD]

定义:在FDF(Firmware Description File)中,[FD] 部分用于描述固件设备(Firmware Device)的参数和配置

参数:

  1. BaseAddress = 0x102000000|gEmulatorPkgTokenSpaceGuid.PcdEmuFdBaseAddress:这里指定了 FD 的基地址。基地址是 FD 在内存中的起始物理地址。在这个示例中,基地址被设置为 0x102000000,并且还引用了一个 PCD(Platform Configuration Database)标记 gEmulatorPkgTokenSpaceGuid.PcdEmuFdBaseAddress,该标记可能用于在不同的构建配置中动态设置基地址。
  2. Size = 0x005a0000|gEmulatorPkgTokenSpaceGuid.PcdEmuFirmwareFdSize:这是指定 FD 的大小。大小表示 FD 占用的字节数。在这个示例中,大小被设置为 0x005a0000,并且也引用了一个 PCD 标记 gEmulatorPkgTokenSpaceGuid.PcdEmuFirmwareFdSize,用于可能的动态配置。
  3. ErasePolarity = 1:这是关于擦除极性的设置,指定了在擦除闪存区域时设置或擦除位的方式。在这里,它被设置为 1。
  4. BlockSize = 0x10000:这是指定 FD 的块大小,块是闪存区域的基本擦除单元。在这个示例中,块大小被设置为 0x10000,表示每个块的大小为 64KB。
  5. NumBlocks = 0x5a:这是指定 FD 中块的数量。在这个示例中,块的数量被设置为 0x5a,表示 FD 中有 90 个块。
[FD.Fv_Recovery]
#
# In OS X PEIMs are really XIP, so we need to make this address match the malloced
# buffer for the FD (0x41000000). If this address does not match the FV will get
# relocated in place (works, but not a great idea).
#
BaseAddress   = 0x102000000|gEmulatorPkgTokenSpaceGuid.PcdEmuFdBaseAddress   #The base address of the FLASH Device.
Size          = 0x005a0000|gEmulatorPkgTokenSpaceGuid.PcdEmuFirmwareFdSize  #The size in bytes of the FLASH Device
ErasePolarity = 1
BlockSize     = 0x10000
NumBlocks     = 0x5a

0x00000000|0x00580000
gEmulatorPkgTokenSpaceGuid.PcdEmuFlashFvRecoveryBase|gEmulatorPkgTokenSpaceGuid.PcdEmuFlashFvRecoverySize
FV = FvRecovery

0x00580000|0x0000c000
gEmulatorPkgTokenSpaceGuid.PcdEmuFlashNvStorageVariableBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
#NV_VARIABLE_STORE
DATA = {
  ## This is the EFI_FIRMWARE_VOLUME_HEADER
  # ZeroVector []
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  # FileSystemGuid: gEfiSystemNvDataFvGuid         =
  #  { 0xFFF12B8D, 0x7696, 0x4C8B, { 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50 }}
  0x8D, 0x2B, 0xF1, 0xFF, 0x96, 0x76, 0x8B, 0x4C,
  0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50,
  # FvLength: 0x20000
  0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
  # Signature "_FVH"       #Attributes
  0x5f, 0x46, 0x56, 0x48, 0xff, 0xfe, 0x04, 0x00,
  # HeaderLength #CheckSum #ExtHeaderOffset #Reserved #Revision
  0x48, 0x00, 0x36, 0x09, 0x00, 0x00, 0x00, 0x02,
  # Blockmap[0]: 2 Blocks * 0x10000 Bytes / Block
  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
  # Blockmap[1]: End
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  ## This is the VARIABLE_STORE_HEADER
!if $(SECURE_BOOT_ENABLE) == FALSE
  #Signature: gEfiVariableGuid =
  #  { 0xddcf3616, 0x3275, 0x4164, { 0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d }}
  0x16, 0x36, 0xcf, 0xdd, 0x75, 0x32, 0x64, 0x41,
  0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d,
!else
  # Signature: gEfiAuthenticatedVariableGuid =
  #  { 0xaaf32c78, 0x947b, 0x439a, { 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92 }}
  0x78, 0x2c, 0xf3, 0xaa, 0x7b, 0x94, 0x9a, 0x43,
  0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92,
!endif
  #Size: 0xc000 (gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize) - 0x48 (size of EFI_FIRMWARE_VOLUME_HEADER) = 0xBFB8
  # This can speed up the Variable Dispatch a bit.
  0xB8, 0xBF, 0x00, 0x00,
  #FORMATTED: 0x5A #HEALTHY: 0xFE #Reserved: UINT16 #Reserved1: UINT32
  0x5A, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
}

0x0058c000|0x00002000
#NV_EVENT_LOG
gEmulatorPkgTokenSpaceGuid.PcdEmuFlashNvStorageEventLogBase|gEmulatorPkgTokenSpaceGuid.PcdEmuFlashNvStorageEventLogSize

0x0058e000|0x00002000
gEmulatorPkgTokenSpaceGuid.PcdEmuFlashNvStorageFtwWorkingBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
#NV_FTW_WORKING
DATA = {
  # EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER->Signature = gEdkiiWorkingBlockSignatureGuid         =
  #  { 0x9e58292b, 0x7c68, 0x497d, { 0xa0, 0xce, 0x65,  0x0, 0xfd, 0x9f, 0x1b, 0x95 }}
  0x2b, 0x29, 0x58, 0x9e, 0x68, 0x7c, 0x7d, 0x49,
  0xa0, 0xce, 0x65,  0x0, 0xfd, 0x9f, 0x1b, 0x95,
  # Crc:UINT32            #WorkingBlockValid:1, WorkingBlockInvalid:1, Reserved
  0xE2, 0x33, 0xF2, 0x03, 0xFE, 0xFF, 0xFF, 0xFF,
  # WriteQueueSize: UINT64
  0xE0, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
}

0x00590000|0x00010000
#NV_FTW_SPARE
gEmulatorPkgTokenSpaceGuid.PcdEmuFlashNvStorageFtwSpareBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
[FV]

定义:在FDF(Firmware Description File)中,[FV] 部分用于描述固件卷(Firmware Volume)的参数和配置。

参数:

  1. FvNameGuid = 6D99E806-3D38-42c2-A095-5F4300BFD7DC:这里指定了 FV 的名称或标识符,使用 GUID(全局唯一标识符)来唯一标识 FV。
  2. FvAlignment = 16:这是 FV 的对齐方式,它指定 FV 在内存中的对齐要求。在这个示例中,FV 被要求以 16 字节的边界对齐。
  3. ERASE_POLARITY = 1:这是擦除极性的设置,它通常用于描述如何在擦除闪存区域时设置或擦除位。在这里,它被设置为 1。
  4. MEMORY_MAPPED = TRUE:这指定了 FV 是否是内存映射型的。如果设置为 TRUE,表示 FV 是通过内存映射方式访问的。
  5. STICKY_WRITE = TRUE:这表示是否启用了“粘性写入”特性。粘性写入通常用于描述写入数据后是否会自动保留在闪存中。
  6. LOCK_CAP = TRUELOCK_STATUS = TRUE:这些参数描述了是否支持闪存区域的锁定功能以及锁定状态。如果 LOCK_CAP 设置为 TRUE,表示支持锁定;LOCK_STATUS 设置为 TRUE,则表示锁定状态已经处于启用状态。
  7. WRITE_DISABLED_CAP = TRUEWRITE_ENABLED_CAP = TRUEWRITE_STATUS = TRUEWRITE_LOCK_CAP = TRUEWRITE_LOCK_STATUS = TRUE:这些参数描述了闪存区域的写入功能,包括是否支持写入禁用和启用,以及写入状态和写入锁定的能力和状态。
  8. READ_DISABLED_CAP = TRUEREAD_ENABLED_CAP = TRUEREAD_STATUS = TRUEREAD_LOCK_CAP = TRUEREAD_LOCK_STATUS = TRUE:类似于写入功能,这些参数描述了闪存区域的读取功能,包括是否支持读取禁用和启用,以及读取状态和读取锁定的能力和状态。
[FV.FvRecovery]
FvNameGuid         = 6D99E806-3D38-42c2-A095-5F4300BFD7DC
FvAlignment        = 16         #FV alignment and FV attributes setting.
ERASE_POLARITY     = 1
MEMORY_MAPPED      = TRUE
STICKY_WRITE       = TRUE
LOCK_CAP           = TRUE
LOCK_STATUS        = TRUE
WRITE_DISABLED_CAP = TRUE
WRITE_ENABLED_CAP  = TRUE
WRITE_STATUS       = TRUE
WRITE_LOCK_CAP     = TRUE
WRITE_LOCK_STATUS  = TRUE
READ_DISABLED_CAP  = TRUE
READ_ENABLED_CAP   = TRUE
READ_STATUS        = TRUE
READ_LOCK_CAP      = TRUE
READ_LOCK_STATUS   = TRUE

#
#  PEI Phase modules
#

#
# 
  • 10
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编译生成 OVMF 是指通过 ed2k 来获得 OVMF 源代码,并将其编译成可执行文件的过程。 首先,我们需要通过 ed2k 下载 OVMF 的源代码ed2k 是一种文件传输协议,可以在网络上找到对应的资源。我们可以使用 ed2k 客户端软件来下载 OVMF。打开 ed2k 客户端,粘贴 OVMF 的 ed2k 链接,然后开始下载。 下载完成后,我们需要解压缩 OVMF 的源代码。可以使用压缩软件(如 WinRAR)将下载的文件解压缩到一个目录。 接下来,我们需要打开命令行终端,并进入到解压缩后的 OVMF 源代码目录。 在命令行输入编译命令来生成 OVMF。具体的编译命令可能因操作系统和编译器而不同。常见的编译命令包括 make、gcc、cmake 等。我们可以查阅 OVMF 的文档或官方网站来获取准确的编译命令。 根据编译命令的要求,执行相应的编译命令,等待编译过程完成。编译过程可能需要一定的时间,取决于计算机性能和源代码的复杂度。 一旦编译完成,我们可以在指定的目录找到生成的 OVMF 可执行文件。该文件就是编译生成的 OVMF。 最后,我们可以将生成的 OVMF 可执行文件用于相应的应用,如虚拟机管理器(例如 QEMU、VirtualBox)来运行 UEFI 镜像。 总结来说,编译生成 OVMF 需要下载 OVMF 源代码,解压缩,进入命令行终端,执行编译命令,等待编译完成,并获取生成的 OVMF 可执行文件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值