为何我的Hello World EFI程序无法正确构建并运行?
EFI程序无法运行:PE二进制文件格式异常问题
问题概述
开发的EFI程序无法运行,EFI Shell返回Command Error Status: Unsupported错误。通过十六进制转储分析,发现生成的PE二进制文件节头起始位置离PE签名过近,导致无法被加载。开发基于经典EFI编程入门教程,构建环境为Debian 12.4 x86_64。
代码文件
Makefile
ARCH=x86_64 OBJS=hello.o TARGET=hello.efi EFIINC=/usr/include/efi EFIINCS=-I$(EFIINC) -I$(EIFFINC)/$(ARCH) -I$(EFIINC)/protocol LIB=/usr/lib64 EFILIB=/usr/lib EFI_CRT_OJBS=$(EFILIB)/crt0-efi-$(ARCH).o EFI_LDS=$(EFILIB)/elf_$(ARCH)_efi.lds CFLAGS=$(EFIINCS) -fno-stack-protector -fpic -fshort-wchar -mno-red-zone -Wall -DEFI_FUNCION_WRAPPER LDFLAGS =-nostdlib -znocombreloc -T $(EFI_LDS) -shared -Bsymbolic -L $(EFILIB) -L $(LIB) $(EFI_CRT_OBJS) all: $(TARGET) hello.so: $(OBJS) ld $(LDFLAGS) $(OBJS) -o $@ -lefi -lgnuefi %.efi: %.so objcopy -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j rel -j rela -j reloc --target=efi-app-$(ARCH) $^ $@
hello.c
#include <efi.h> #include <efilib.h> EFI_STATUS EFIAPI efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) { InitializeLib(ImageHandle, SystemTable); Print(L"Hello, World\n"); return EFI_SUCCESS; }
测试流程及错误表现
- 构建完成后,将
hello.efi复制到磁盘镜像,通过以下命令启动QEMU:qemu-system-x86_64 -enable-kvm -bios /usr/share/qemu/OVMF.fd -nodefaults -display gtk -vga std -hda target - 在EFI Shell中执行程序时出现错误:
注:官方演示程序FS0:\> dir Directory of: FS0:\ 12/31/2023 48,181 exit.efi 12/31/2023 41,494 hello.efi FS0:\> hello.efi Command Error Status: Unsupportedexit.efi可正常运行
二进制文件分析结果
objdump输出
$ objdump -f -h hello.efi hello.efi: file format pei-x86-64 architecture: i386:x86-64, flags 0x00000030: HAS_SYMS, HAS_LOCALS start address 0x0000000000000000 Sections: Idx Name Size VMA LMA File off Algn 0 .text 00005bf0 0000000000003000 0000000000003000 00000138 2**4 CONTENTS, ALLOC, LOAD, READONLY, CODE 1 .data 00001d00 0000000000009000 0000000000009000 00005d38 2**5 CONTENTS, ALLOC, LOAD, DATA 2 .dynamic 00000110 000000000000b000 000000000000b000 00007b38 2**3 CONTENTS, ALLOC, LOAD, DATA 3 .dynsym 000000d8 000000000000d000 000000000000d000 00007d38 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA
十六进制转储头部
$ hexdump -C hello.efi | head -n 16 00000000 4d 5a 90 00 03 00 00 00 04 00 00 00 ff ff 00 00 |MZ..........ÿÿ..| 00000010 b8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 |¸.......@.......| 00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00 |................| 00000040 0e 1f ba 0e 00 b4 09 cd 21 b8 01 4c cd 21 54 68 |..º..´.Í!¸.LÍ!Th| 00000050 69 73 20 70 72 6f 67 72 61 6d 20 63 61 6e 6e 6f |is program canno| 00000060 74 20 62 65 20 72 75 6e 20 69 6e 20 44 4f 53 20 |t be run in DOS | 00000070 6d 6f 64 65 2e 0d 0d 0a 24 00 00 00 00 00 00 00 |mode....$.......| 00000080 50 45 00 00 64 86 04 00 00 00 00 00 38 7f 00 00 |PE..d.......8...| 00000090 12 01 00 00 00 00 05 02 2e 74 65 78 74 00 00 00 |.........text...| 000000a0 f0 5b 00 00 00 30 00 00 00 5c 00 00 38 01 00 00 |ð[...0...\..8...| 000000b0 00 00 00 00 00 00 00 00 00 00 00 00 20 00 50 60 |............ .P`| 000000c0 2e 64 61 74 61 00 00 00 00 1d 00 00 00 90 00 00 |.data...........| 000000d0 00 1e 00 00 38 5d 00 00 00 00 00 00 00 00 00 00 |....8]..........| 000000e0 00 00 00 00 40 00 60 c0 2e 64 79 6e 61 6d 69 63 |....@.`À.dynamic| 000000f0 10 01 00 00 00 b0 00 00 00 02 00 00 38 7b 00 00 |.....°......8{..|
核心问题:节头起始位置离PE签名过近,导致EFI无法正常加载该二进制文件
内容的提问来源于stack exchange,提问作者Joshua
相关产品推荐
相关产品推荐

