2. 编写HelloWorld UEFI应用
任务目标
编写一个最小的UEFI应用程序,在UEFI Shell中运行时输出字符串 Hello, UEFI!,并编译生成可加载的 .efi 可执行文件。
环境与依赖
- 操作系统:Linux(本文以Ubuntu为例)或Windows(需安装MSYS2)
- 编译器:
x86_64-w64-mingw32-gcc(MinGW-w64交叉编译器),用于生成PE32+格式的EFI可执行文件 - UEFI头文件:
gnu-efi开发包(提供基本类型定义与协议接口声明)
Ubuntu安装命令:
sudo apt install gcc-mingw-w64-x86-64 gnu-efi
核心代码
以下代码使用GNU-EFI的封装方式,通过 efi_main 作为入口点,调用 Print 服务输出字符串,然后返回 EFI_SUCCESS 退出应用。
#include <efi.h>
#include <efilib.h>
EFI_STATUS
efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
// 初始化GNU-EFI运行时库,使Print等辅助函数可用
InitializeLib(ImageHandle, SystemTable);
// 输出字符串到UEFI控制台
Print(L"Hello, UEFI!\r\n");
// 返回成功状态,应用正常退出
return EFI_SUCCESS;
}
编译与运行
将上述代码保存为 hello.c,在同一目录下执行以下命令编译:
x86_64-w64-mingw32-gcc -c -I/usr/include/efi -I/usr/include/efi/x86_64 \
-fno-stack-protector -fpic -fshort-wchar -mno-red-zone -Wall hello.c
x86_64-w64-mingw32-ld -shared -Bsymbolic -L/usr/lib -T/usr/lib/elf_x86_64_efi.lds \
-o hello.efi hello.o -lefi -lgcc
生成 hello.efi 后,将其复制到UEFI启动盘(FAT32格式)的 EFI/BOOT 目录下,或直接在UEFI Shell中通过文件系统访问该文件。
运行方式:
- 在UEFI Shell中切换到文件所在分区(如
fs0:),执行hello.efi; - 或将
hello.efi作为启动项加载(需在固件设置中配置)。
验证方法
应用执行后,屏幕应显示一行文本 Hello, UEFI!,随后自动返回Shell提示符。若在OVMF(开源UEFI固件)虚拟机中测试,可直接在QEMU窗口中观察输出。
通过条件:控制台出现且仅出现一次 Hello, UEFI!,无错误码或崩溃信息。
常见问题
- 编译报错找不到头文件:确认
-I参数路径与gnu-efi安装位置一致,不同发行版路径可能为/usr/include/efi或/usr/local/include/efi。 - 链接失败:检查
-T指定的链接脚本路径是否正确,该脚本由gnu-efi提供,用于生成PE32+格式。 - 运行时无输出:确认
hello.efi确实在UEFI环境(而非传统BIOS模式)下执行,且文件系统可被固件识别。