UEFI原理与编程实践--FDF文件

实际书籍中并没有讲这一块的,不过这块还是挺重要的,因为很多人一看fdf文件就很懵,不知道细节的可以说完全看不懂,FDF文件是什么,说的直白一点,就是盖房子的设计图,fdf说编译器来,你给我输出一个这样层次的FD文件,这个FD文件就是大家经常烧录的BIOS固件。

FD:固件设备,可以转化为BIN文件,熟悉的OVMF.FD就是典型代表

FV:固件卷,说固件卷很难懂的话,直接说固件块总行吧,就是FD被切割成了一块一块的,这一块一块的就是固件卷

目前先主要说FV吧,FD知道概念就行

FV

啥是FV啊,FV就是固件卷,那究竟什么又是固件卷啊,说白了,就是存放某个阶段的所有image,这个咋说呢,比如一个DXE driver,最终编译会生成一个.efi,其实这个.efi就保存在一个固件卷中,而这个固件卷保存所有DXE阶段产生的.efi,这个就和UEFI的名字联系起来了(题外话)UEFI:统一可拓展固件接口,它的模块化我觉得就在于此,整个BIOS文件就是多个.efi可执行文件的集合体,先把流水线建好,然后约好了,你先走这个.efi,然后再走那个.efi。。。

玩BIOS的,经常看到开机的时候有个logo,当初做新手换个logo觉得很神奇,但是不知道怎么加载的,其实,这个就是个可视化的FV(当然如果fdf文件不包含logo FV的话也有另外的加载方式,这个另当别论),一张图片作为数据被保存在一个独有的固件卷中,在开机的时候,再把它找到,解析出来显示,就是大家看到的logo啦。

看一下FV的格式,找一张没侵权的吧,这个应该是通用的:

0x00020000|0x00020000

#gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize

DATA = {

  # ZeroVector []

  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  # FileSystemGuid

  0x8D, 0x2B, 0xF1, 0xFF, 0x96, 0x76, 0x8B, 0x4C, 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50,

  # FvLength: 0x50000

  0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,

  #Signature "_FVH"       #Attributes

  0x5F, 0x46, 0x56, 0x48, 0xFF, 0xFE, 0x04, 0x00,

  #HeaderLength #CheckSum #ExtHeaderOffset #Reserved #Revision

  0x48, 0x00, 0x30, 0x09, 0x00, 0x00, 0x00, 0x02,

  #Blockmap[0]: 5 Blocks  0x10000 Bytes / Block

  0x05, 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) == TRUE

  # 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,

!else

  #  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,

!endif

  #Size: (gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize) - 0x48(size of EFI_FIRMWARE_VOLUME_HEADER)

  0xB8, 0xFF, 0x01, 0x00,

  #FORMATTED: 0x5A #HEALTHY: 0xFE #Reserved: UINT16 #Reserved1: UINT32

  0x5A, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00

}

看完发现眼花缭乱,这都写的啥呀,这个其实就是FV在固件中存放的实际显示,打开一个固件,咱们搜索_FVH:

 照着上面的代码比对一下,是不是相差无几?这里还有个小技巧,你可以通过搜索_FVH(ASCII)找出你的BIOS固件有几个FV哦,这个在代码中也是有些用处的。

前面咱们介绍了FV实际的结构(代码注释写的有),通过查看FDF文件,发现还有一种表现形式:

[FV.FVMAIN_LOGO]

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
FvNameGuid         = 35C40558-3BF2-4575-BD6C-540F5B4EDE46 

xxxxxxxxxx  logo.bmp

 这样写也是可以滴,但是还要注意一点:

0x003B0000|0x00080000

gPhytiumPlatformTokenSpaceGuid.PcdLogoBaseAddress|gPhytiumPlatformTokenSpaceGuid.PcdLogoSize

FV = FVMAIN_LOGO

 你要告诉编译的,你的这个固件放在那个地方,占用多少空间,这是前提。在PCD的使用中就说了,有的PCD变量在fdf文件中也有用到,就是这了,其中PcdLogoBaseAddress的值为多少,自己尝试去获取一下,后面的size也是。

所以fdf文件总的来说就两部分,属于先总后分,先FD后FV,总的概括一下,然后再仔细介绍。至于怎么去找FV啊啥的,后续在BIOS实战中再写吧

最后看一下它是怎么被发现编译的:

 ok,FDF文件就先介绍到这里

猜你喜欢

转载自blog.csdn.net/u011397314/article/details/121513424
fdf