如何使用C++构建UEFI应用,编译后Qemu启动卡住求解决方案或POC代码
问题排查与解决方案
现有代码问题原因
- 缺少
extern "C"修饰入口函数:C++编译器会对函数名做名字修饰,而GNU EFI要求入口函数efi_main使用C ABI,不加修饰会导致固件找不到合法入口点,直接卡住启动流程。 - 缺少输出刷新逻辑:UEFI的
Print接口默认会做输出缓冲,未刷新就进入死循环会导致字符串无法正常打印到屏幕。 hlt指令未关中断:开中断状态下hlt会在收到中断时恢复执行,死循环逻辑会被打破。
修正后的可用C++ UEFI POC代码
#include <efi.h> #include <efilib.h> #include <efiprot.h> // 必须加extern "C"指定使用C ABI,避免C++名字修饰导致入口点失效 extern "C" EFI_STATUS EFIAPI efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) { InitializeLib(ImageHandle, SystemTable); // 末尾加\n触发行缓冲刷新,保证内容正常输出 Print(L"XENON OS VER 0.02\n"); // 关中断后执行hlt,确保稳定停在死循环 for(;;) __asm__ volatile ("cli; hlt"); return EFI_SUCCESS; }
完整编译链接流程(x86_64架构为例,需将gnu-efi-dir替换为本地gnu-efi库的实际路径)
- 编译目标文件
gcc -Ignu-efi-dir/inc -Ignu-efi-dir/inc/x86_64 -fpic -ffreestanding -fno-stack-protector -fno-stack-check -fshort-wchar -mno-red-zone -maccumulate-outgoing-args -c main.cpp -o main.o
- 链接生成共享对象
ld -shared -Bsymbolic -Lgnu-efi-dir/lib -Tgnu-efi-dir/gnuefi/elf_x86_64_efi.lds gnu-efi-dir/gnuefi/crt0-efi-x86_64.o main.o -o main.so -lgnuefi -lefi
- 格式转换生成最终EFI可执行文件
objcopy -j .text -j .sdata -j .data -j .reloc --target=efi-app-x86_64 main.so main.efi
测试注意事项
- 将生成的
main.efi放到FAT32格式的镜像EFI/BOOT/BOOTX64.EFI路径下,再用Qemu启动即可正常看到输出 - 确保使用的gnu-efi库版本和编译架构匹配,x86_64、ia32、aarch64的链接脚本和crt0文件各不相同
内容的提问来源于stack exchange,提问作者Elhadede
相关产品推荐
相关产品推荐

