이번 장에서는 BaseTools 유틸리티 EfiRom을 사용해 OptionROM 이미지를 분석한다. EDKII 폴더에서 . edksetup.sh를 실행하면 EfiRom을 사용할 수 있다.
$EfiRom-hUsage:EfiRom-fVendorId-iDeviceId [options] [file name<s>]Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.Options:-oFileName,--outputFileNameFilewillbecreatedtostoretheoutputcontent.-eEfiFileNameEFIPE32imagefiles.-ecEfiFileNameEFIPE32imagefilesandwillbecompressed.-bBinFileNameLegacybinaryfiles.-lClassCodeHexClassCodeinthePCIdatastructureheader.-rRevHexRevisioninthePCIdatastructureheader.-nNottoautomaticallysettheLASTbitinthelastfile.-fVendorIdHexPCIVendorIDforthedeviceOpROM,mustbespecified-iDeviceIdOneormorehexPCIDeviceIDsforthedeviceOpROM,mustbespecified-p,--pci23DefaultlayoutmeetsPCI3.0specificationsspecifyingthisflagwillforaPCI2.3layout.-d,--dumpDumptheheadersofanexistingoptionROMimage.-v,--verboseTurnonverboseoutputwithinformationalmessages.--versionShowprogram's version number and exit. -h, --help Show this help message and exit. -q, --quiet Disable all messages except FATAL ERRORS. --debug [#,0-9] Enable debug messages at level #.
PXE 부팅에 특정 PCI 네트워크 카드를 사용하는 방법을 알기 위해서는 BIOS에서 일부 네트워크 카드를 알아야 한다. 그러나 BIOS는 OS가 아니므로 모든 PCI 네트워크 카드용 드라이버를 포함할 수 없다. 따라서 이 문제는 OptionROM 펌웨어를 통해 해결한다. PCI 네트워크 카드에는 PXE 부팅에 필요한 모든 코드가 포함되어 있다. 그러나 모든 카드에 그런 펌웨어가 있는 것은 아니기 때문에 iPXE 프로젝트를 활용할 수 있다.
이제 SeaBIOS VGA 이미지를 빌드한다.
아래 명령어를 통해 필요한 패키지를 설치하고, SeaBIOS 소스 다운로드 및 빌드를 진행한다.
SeaBIOS를 빌드하기 전에 VGA ROM에 대한 설정을 변경해야 하기 때문에 아래와 menuconfig 화면에서 아래 경로를 따라 qemu bochs-display support를 선택한다.
설정을 저장하고 빌드를 진행한다.
빌드 후 VGA Option ROM은 out/vgabios.bin으로 존재한다. EfiRom은 ROM 파일의 확장자가 *.rom일 경우에만 사용할 수 있으므로 vgabios.bin 파일을 vgabios.rom 으로 복사본을 생성한다. EfiRom을 사용해 vgabios.rom 파일을 덤프해보면 아래와 같이 확인할 수 있다.
결과는 QEMU 시스템에서 유틸리티를 사용하여 확인한 것과 유사한 정보이다. PCI Vendor/Device 쌍이 1234:1111로 설정된 것을 확인할 수 있다.
$ sudo apt-get install liblzma-dev
$ make bin-x86_64-efi/ipxe.efi # EFI app with all devices
$ make bin-x86_64-efi/8086100e.efirom # EFI ROM vendev: 8086:100e
$ make bin/8086100e.rom # Legacy ROM vendev: 8086:100e
$ EfiRom -d bin/8086100e.rom
Image 1 -- Offset 0x0
ROM header contents
Signature 0xAA55
PCIR offset 0x001C
Signature PCIR
Vendor ID 0x8086
Device ID 0x100E
Length 0x001C
Revision 0x0003
DeviceListOffset 0x4BF
Device list contents
0x100E
Class Code 0x020000
Image size 0x10C00
Code revision: 0x0001
MaxRuntimeImageLength 0x07
ConfigUtilityCodeHeaderOffset 0x00
DMTFCLPEntryPointOffset 0x00
Indicator 0x80 (last image)
Code type 0x00
$ EfiRom -d bin-x86_64-efi/8086100e.efirom
EfiRom: ERROR 1002: No PciRom input file
No *.rom input file
$ cp bin-x86_64-efi/8086100e.efirom bin-x86_64-efi/8086100e.rom
$ EfiRom -d bin-x86_64-efi/8086100e.rom
Image 1 -- Offset 0x0
ROM header contents
Signature 0xAA55
PCIR offset 0x001C
Signature PCIR
Vendor ID 0x8086
Device ID 0x100E
Length 0x0018
Revision 0x0000
DeviceListOffset 0x00
Class Code 0x020000
Image size 0x1A000
Code revision: 0x0000
MaxRuntimeImageLength 0x00
ConfigUtilityCodeHeaderOffset 0x87
DMTFCLPEntryPointOffset 0x00
Indicator 0x80 (last image)
Code type 0x03 (EFI image)
EFI ROM header contents
EFI Signature 0x0EF1
Compression Type 0x0001 (compressed)
Machine type 0x8664 (X64)
Subsystem 0x000B (EFI boot service driver)
EFI image offset 0x0038 (@0x38)
$ make bin-x86_64-efi/8086100e.efidrv
$ EfiRom -f 0x8086 -i 0x100e -b bin/8086100e.rom -ec bin-x86_64-efi/8086100e.efidrv -o bin/8086100e_optionrom.rom
$ EfiRom -d bin/8086100e_optionrom.rom
Image 1 -- Offset 0x0
ROM header contents
Signature 0xAA55
PCIR offset 0x001C
Signature PCIR
Vendor ID 0x8086
Device ID 0x100E
Length 0x001C
Revision 0x0003
DeviceListOffset 0x4BF
Device list contents
0x100E
Class Code 0x020000
Image size 0x10C00
Code revision: 0x0001
MaxRuntimeImageLength 0x07
ConfigUtilityCodeHeaderOffset 0x00
DMTFCLPEntryPointOffset 0x00
Indicator 0x00
Code type 0x00
Image 2 -- Offset 0x10C00
ROM header contents
Signature 0xAA55
PCIR offset 0x001C
Signature PCIR
Vendor ID 0x8086
Device ID 0x100E
Length 0x001C
Revision 0x0003
DeviceListOffset 0x00
Class Code 0x000000
Image size 0x1A000
Code revision: 0x0000
MaxRuntimeImageLength 0x00
ConfigUtilityCodeHeaderOffset 0x00
DMTFCLPEntryPointOffset 0x00
Indicator 0x80 (last image)
Code type 0x03 (EFI image)
EFI ROM header contents
EFI Signature 0x0EF1
Compression Type 0x0001 (compressed)
Machine type 0x8664 (X64)
Subsystem 0x000B (EFI boot service driver)
EFI image offset 0x0038 (@0x10C38)
config VGA_VID
depends on VGA_PCI
hex
prompt "PCI Vendor ID" if OVERRIDE_PCI_ID
default 0x1013 if VGA_CIRRUS
default 0x1002 if VGA_ATI
default 0x1234 if VGA_BOCHS_STDVGA
default 0x15ad if VGA_BOCHS_VMWARE
default 0x1b36 if VGA_BOCHS_QXL
default 0x1af4 if VGA_BOCHS_VIRTIO
default 0x100b if VGA_GEODEGX2
default 0x1022 if VGA_GEODELX
default 0x1234 if DISPLAY_BOCHS <--------------
default 0x0000
help
Vendor ID for the PCI ROM
config VGA_DID
depends on VGA_PCI
hex
prompt "PCI Vendor ID" if OVERRIDE_PCI_ID
default 0x00b8 if VGA_CIRRUS
default 0x5159 if VGA_ATI
default 0x1111 if VGA_BOCHS_STDVGA
default 0x0405 if VGA_BOCHS_VMWARE
default 0x0100 if VGA_BOCHS_QXL
default 0x1050 if VGA_BOCHS_VIRTIO
default 0x0030 if VGA_GEODEGX2
default 0x2081 if VGA_GEODELX
default 0x1111 if DISPLAY_BOCHS <---------------
default 0x0000
help
Device ID for the PCI ROM
config DISPLAY_BOCHS
depends on QEMU
bool "qemu bochs-display support"
select VGA_EMULATE_TEXT
help
Build support for the qemu bochs-display device, which
is basically qemu stdvga without the legacy vga
emulation, supporting only 16+32 bpp VESA video modes
in a linear framebuffer. So this uses cbvga text mode
emulation.
The bochs-display device is available in qemu
v3.0+. The vgabios works with the qemu stdvga too (use
"qemu -device VGA,romfile=/path/to/vgabios.bin")".
$ sudo apt-get install python libncurses-dev
$ git clone https://github.com/coreboot/seabios.git
$ cd seabios
$ make menuconfig
VGA ROM ---> VGA Hardware Type
qemu bochs-display support 선택