前面介绍了如何EDK2在编译的最后过程中使用了 GenFds 进行打包。分析的目标是 QEMU 的 BIOS 文件 OVMF.FD,使用 UEFITool NE 打开之后,可以看到有三个 FV ,我们以中间的为例,分析它的生成方法。整体分析过程比较枯燥,对于大多数人来说了解大致的步骤就可以了。
首先,在 FDF 文件中,给出了这个 FV 的GUID 可以看到:
[FV.FVMAIN_COMPACT]
FvNameGuid = 48DB5E17-707C-472D-91CD-1613E7EF51B0
FvAlignment = 16
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
上面的FV 是由两个 Section 构成的,一个是 PEIFV,另一个是 DXEFV:
1.下面是对于 PEIFV 的定义:
[FV.PEIFV]
FvNameGuid = 6938079B-B503-4E3D-9D24-B28337A25806
BlockSize = 0x10000
FvAlignment = 16
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
APRIORI PEI {
INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf
}
2.下面是 DXEFV 的定义
[FV.DXEFV]
FvForceRebase = FALSE
FvNameGuid = 7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1
BlockSize = 0x10000
FvAlignment = 16
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
APRIORI DXE {
INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
INF OvmfPkg/AmdSevDxe/AmdSevDxe.inf
!if $(SMM_REQUIRE) == FALSE
INF OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
!endif
}
这里可以使用 UEFITool 直接将内容解压出来,例如:
可以用 Z7 查看解压出来的文件,但是7Z 只能看到 PEIFV 看不到DXEFV, 我猜测是因为格式原因,只能看到前面一半:
具体的 DXEFV 和 PEIFV 可以在 \Build\OvmfX64\DEBUG_VS2015x86\FV 下面看到:
有了这两个文件,就可以生成出现在 OVMF.FD 中的 FV 了。为了便于描述,使用下面的流程图:
CMD1: 生成 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792SEC1.1fv.sec
GenSec -s EFI_SECTION_FIRMWARE_VOLUME_IMAGE -o d:\i2c\Build\OvmfX64\DEBUG_VS2015x86\FV\Ffs\9E21FD93-9C72-4c15-8C4B-E77F1DB2D792FVMAIN_COMPACT\9E21FD93-9C72-4c15-8C4B-E77F1DB2D792SEC1.1fv.sec d:\i2c\Build\OvmfX64\DEBUG_VS2015x86\FV\PEIFV.Fv
CMD2: 生成9E21FD93-9C72-4c15-8C4B-E77F1DB2D792SEC1.2fv.sec
GenSec -s EFI_SECTION_FIRMWARE_VOLUME_IMAGE -o d:\i2c\Build\OvmfX64\DEBUG_VS2015x86\FV\Ffs\9E21FD93-9C72-4c15-8C4B-E77F1DB2D792FVMAIN_COMPACT\9E21FD93-9C72-4c15-8C4B-E77F1DB2D792SEC1.2fv.sec d:\i2c\Build\OvmfX64\DEBUG_VS2015x86\FV\DXEFV.Fv
CMD3: 将上面两个文件合成为一个文件 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792SEC1.guided.dummy
GenSec --sectionalign 128 --sectionalign 16 -o d:\i2c\Build\OvmfX64\DEBUG_VS2015x86\FV\Ffs\9E21FD93-9C72-4c15-8C4B-E77F1DB2D792FVMAIN_COMPACT\9E21FD93-9C72-4c15-8C4B-E77F1DB2D792SEC1.guided.dummy d:\i2c\Build\OvmfX64\DEBUG_VS2015x86\FV\Ffs\9E21FD93-9C72-4c15-8C4B-E77F1DB2D792FVMAIN_COMPACT\9E21FD93-9C72-4c15-8C4B-E77F1DB2D792SEC1.1fv.sec d:\i2c\Build\OvmfX64\DEBUG_VS2015x86\FV\Ffs\9E21FD93-9C72-4c15-8C4B-E77F1DB2D792FVMAIN_COMPACT\9E21FD93-9C72-4c15-8C4B-E77F1DB2D792SEC1.2fv.sec
CMD4: 对上面的文件进行压缩,生成 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792SEC1.tmp 文件,从 11MB 压缩到了1MB左右
LzmaCompress -e -o d:\\i2c\\Build\\OvmfX64\\DEBUG_VS2015x86\\FV\\Ffs\\9E21FD93-9C72-4c15-8C4B-E77F1DB2D792FVMAIN_COMPACT\\9E21FD93-9C72-4c15-8C4B-E77F1DB2D792SEC1.tmp d:\\i2c\\Build\\OvmfX64\\DEBUG_VS2015x86\\FV\\Ffs\\9E21FD93-9C72-4c15-8C4B-E77F1DB2D792FVMAIN_COMPACT\\9E21FD93-9C72-4c15-8C4B-E77F1DB2D792SEC1.guided.dummy
CMD5: 继续打包生成 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792SEC1.tmp
GenSec -s EFI_SECTION_GUID_DEFINED -g EE4E5898-3914-4259-9D6E-DC7BD79403CF -r PROCESSING_REQUIRED -o d:\i2c\Build\OvmfX64\DEBUG_VS2015x86\FV\Ffs\9E21FD93-9C72-4c15-8C4B-E77F1DB2D792FVMAIN_COMPACT\9E21FD93-9C72-4c15-8C4B-E77F1DB2D792SEC1.guided d:\i2c\Build\OvmfX64\DEBUG_VS2015x86\FV\Ffs\9E21FD93-9C72-4c15-8C4B-E77F1DB2D792FVMAIN_COMPACT\9E21FD93-9C72-4c15-8C4B-E77F1DB2D792SEC1.tmp
CMD6:生成 FFS文件,9E21FD93-9C72-4c15-8C4B-E77F1DB2D792.ffs
GenFfs -t EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE -g 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 -o d:\i2c\Build\OvmfX64\DEBUG_VS2015x86\FV\Ffs\9E21FD93-9C72-4c15-8C4B-E77F1DB2D792FVMAIN_COMPACT\9E21FD93-9C72-4c15-8C4B-E77F1DB2D792.ffs -i d:\i2c\Build\OvmfX64\DEBUG_VS2015x86\FV\Ffs\9E21FD93-9C72-4c15-8C4B-E77F1DB2D792FVMAIN_COMPACT\9E21FD93-9C72-4c15-8C4B-E77F1DB2D792SEC1.guided
CMD7:最终生成 FVMAIN_COMPACT.Fv,用 Beyond Compare 可以看到这个是 OVMF.FD 的一部分。
GenFv -a d:\i2c\Build\OvmfX64\DEBUG_VS2015x86\FV\Ffs\FVMAIN_COMPACT.inf -o d:\i2c\Build\OvmfX64\DEBUG_VS2015x86\FV\FVMAIN_COMPACT.Fv -i d:\i2c\Build\OvmfX64\DEBUG_VS2015x86\FV\FVMAIN_COMPACT.inf
生成的FVMAIN_COMPACT.Fv 就是 OVMF 中间的一部分。