UEFI固件安全 · 2023年6月19日 0

VBIOS原理及修改方式

VBIOS原理学习及修改方法。

GOP与VBIOS原理

GOP与VBIOS区别

VBIOS是由IBM PC衍生的Video BIOS,用于初始化显卡,为加载显卡驱动之前的基本视频输出提供INT 10h中断和VESA BIOS扩展。作为常见的Option ROM,在POST后由BIOS执行。

GOP(Graphics output protocol)——图形输出协议,GOP提供对硬件帧缓冲区的访问,提供显示的基本功能。为取代VGA BIOS,并在没有CSM的情况下使用。

Intel的GOP会放在BIOS中,主要包括三部分:

image-20230619152420302
  1. IntelGopDriver.efi:GOP的DXE驱动
  2. IntelGraphicsPeim.efi:PEI阶段的GOP
  3. VBT:GOP配置文件

调用阶段如下:

image-20230619152826956

在OS启动过程中,OS Loader会通过 ExitBootervices()通知 Driver 退出,这时 GOP 会在从系统中卸载。但是 Intel GFX Driver会继续使用 VBT 提供的配置信息。

显卡VBIOS结构

独显中的VBIOS通常会包括VBIOS和GOP两个镜像,和UEFI BIOS中的VBIOS一样,是一个PCI Expansion PROM的结构。

PCIR头和数据结构定义

PCIR头通常为28个字节的数据,其定义如下:

byte offsetvaluedescription
0055PROM signature
01aaPROM signature
02-0333 00SPARC reserved value(可扩展处理器架构保留值)
04-1700 00为特有的处理器架构保留的数据
18-191c 00指向PCI数据结构的指针
1a-1b00 00填充

PCIR数据结构通常为24个字节,其定义如下:

Byte OffsetDescription/(Hex. value)
00-03Signature : P C I R (50 43 49 52)
04-05Vendor ID
06-07Device ID
08-09product data指针
0A-0BPCI data structure 长度(18 00)
0CPCI data structure 版本号
0D编程接口代码
0E子类代码
0F类代码
10-11image length in 512 bytes
12-13Revision level of code/data
14Code type
15标识字节,如果是最后一个镜像则值为0x80
16-17保留值

注意这里的标识字节,现代显卡一般会包含两个PCI ROM,分别对应VBT和GOP,如RX550的VBIOS:

image-20230714161814751
image-20230714161841274

这个GOP的PCI ROM的标识字节就为0x80,如果要禁用GOP,那么就可以把ATOMBIOS的标识字节改为0x80。

但是修改后要不要修改CRC校验和,还是个问题。校验块的位置似乎不包括这个头的数据。

以上是对于通用VBIOS的PCIR头和结构定义,而AMD显卡的VBIOS——Atombios,在此基础上又有细分了几个表的定义。

PCIR头后跟了一段ATI magic,用于标识Atombios:

OffsetSizeDescription
0x00WordBIOS Magic, should be 0xAA55
0x02byteImage SIZE = value * 512
0x3010 bytesATI Magic, should be ” 761295520″
0x48WordAtom ROM Table Base

如RX550的VBIOS:

image-20230714110011039

0x48字节处的值(0x234)指向了ATOM ROM表的偏移:

image-20230714110156458

0x02字节处标识ATOMBIOS IMAGE的大小,如:

0x73 * 512 = 0xE600

image-20230718152007477

同时PCIR头的0x10-0x11偏移处也标识了IMAGE的大小,计算方法同上:

image-20230719160740310

ATOM ROM table

ATOM ROM表定义如下:

OffsetSizeDescription
0x004 bytesCommon header
0x044 bytesAtom Magic, should be “ATOM”
0x08WordBIOS运行时的段地址
0x0AWordProtected Mode Info Offset
0x0CWordConfig Filename Offset
0x0EWordCRC Block Offset
0x10WordName String offset(可为0,最大512bytes)
0x12WordInt 10 offset
0x14WordPCI总线设备初始化代码
0x16WordIO基址
0x18WordSubsystem Vendor ID
0x1AWordSubsystem ID
0x1CWordPCI Info Offset
0x1EWordCommand Table Base
0x20WordData Table Base
0x22ByteExtended Function Code
0x23ByteReserved

根据该表定义可以看出下面还定义了好几个表的偏移地址。需要注意的是,这个偏移是针对整个镜像文件开始的位置,而不是ATOM ROM表开始的位置

大多数表使用的头定义如下:

Common header

OffsetSizeDescription
0x00Word表定义结构的长度
0x02Byte表格式修订,当解析器不向后兼容时更改
0x03Byte表内容修订

command table

OffsetSizeDescription
0x004 bytesCommon Header
0x04x wordsArray offsets of commands

command format

命令格式定义:

OffsetSizeDescription
0x00WordCommand Length
0x02WordReserved
0x04ByteWS?
0x05BytePS – Parameter Stack
0x06-0x??????Command bytecode

RX550的command table偏移:

image-20230714160445057

该表定义了结构的大小为A6个字节,以及各个命令数组的偏移:

image-20230714160620189

Data table

OffsetSizeDescription
0x004 bytesCommon Header
0x04WordUtilityPipeline
0x06WordMultimediaCapabilityInfo
0x08WordMultimediaConfigInfo
0x0AWordStandardVesa_Timing
0x0CWordFirmwareInfo
0x0EWordPaletteData
0x10WordLCD_Info
0x12WordDIGTransmitterInfo
0x14WordAnalogTV_Info
0x16WordSupportedDevicesInfo
0x18WordGPIO_I2C_Info
0x1AWordVRAM_UsageByFirmware
0x1CWordGPIO_Pin_LUT
0x1EWordVESA_ToInternalModeLUT
0x20WordComponentVideoInfo
0x22WordPowerPlayInfo
0x24WordCompassionateData
0x26WordSaveRestoreInfo
0x28WordPPLL_SS_Info
0x2AWordOemInfo
0x2CWordXTMDS_Info
0x2EWordMclkSS_Info
0x30WordObject_header
0x32WordIndirectIOAccess
0x34WordMC_InitParameter
0x36WordASIC_VDDC_Info
0x38WordASIC_InternalSS_Info
0x3AWordTV_VideoMode
0x3CWordVRAM_Info
0x3EWordMemoryTrainingInfo
0x40WordIntegratedSystemInfo
0x42WordASIC_ProfilingInfo
0x44WordVoltageObjectInfo
0x46WordPowerSourceInfo

command表后紧接着就是data表,包含了各类信息表的偏移:

image-20230714160846658

INT 10H中断

该中断处理程序用于提供视频显示服务,包括设置视频模式、字符和字符串输出以及在图形模式下的读取和写入像素。

VBIOS提取

用mmtool可提取VBIOS/VBT:

image-20230619105557543

实际上就是CSMCORE RAW里的部分内容。

hex查看提取的内容:

version OROM VBIOS:HASWELL 2173

version VBT:AA 00 -> AA(v1.70)

size VBT: ff 10 -> 10ff (4351 byte)

image-20230619110057275

使用Intel BMP工具可编辑VBIOS镜像,需要选择对应版本的BSF脚本:

image-20230619112400124
image-20230619112420944

显卡VBIOS读写

GPU-Z可查看显卡信息,并读取VBIOS:

A卡使用amdvbflash工具,-i参数读取适配器id:

写入VBIOS:amdvbflash.exe -p -f [id] <*.rom>

A卡使用GopInfoX.exe可查看GOP信息:

VBIOS修改

修改CRC对刷写工具的解析有影响,未修改的固件无法识别ID,而修改后的可以:

image-20230718104404332

修改方式为把ATOMBIOS尾部的FF修改为7F,平衡CRC校验和(0xFF-0x80=0x7F):

image-20230718104430826

把GOP镜像全填充为FF,并在最后0x1000个字节处填充csminsert数据。但这样就无法修改单个数据来平衡校验和了。

修改校验和,用PolarisBIOSEditor打开,会提示未修改校验和,点确定,再SAVE AS另存为文件后即可修复校验和:

image-20230718153910183
image-20230718154008408

另外一提,这个校验和的位置为0x21的偏移处:

image-20230718154307891

用amdvbflash写入时可以正常识别ID了:

image-20230718154158764

不出所料,这样暴力修改后刷进去显卡就变砖了。

恢复方法

找个能设置集显优先输出的主板,在插入了RX 550的情况下,从集显进入系统,使用amdvbflash -i可以识别到适配器id,刷回原版固件即可。

如MSI B360M MORTAR的设置: