2. Hello World UEFI应用
任务目标
编写一个最小的UEFI应用程序,在UEFI Shell或启动环境中输出字符串 Hello World,并编译生成可加载的 .efi 可执行文件。本案例聚焦于EDK2环境下UEFI应用的标准入口点实现与编译流程。
环境与依赖
- EDK2开发环境(已在
Conf/target.txt中配置好工具链,如GCC5或VS2019) - 已执行
edksetup.sh(Linux)或edksetup.bat(Windows)完成环境初始化 - 已创建或已有工作区(如
OvmfPkg或自定义包目录)
实现步骤
在EDK2包目录下创建应用源码文件 HelloWorld.c,并在包级 .dsc 文件中注册该组件。核心实现如下:
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/UefiApplicationEntryPoint.h>
/**
UEFI应用入口点。
@param[in] ImageHandle 固件分配的镜像句柄。
@param[in] SystemTable 指向系统表的指针。
@return 始终返回 EFI_SUCCESS,表示应用正常退出。
**/
EFI_STATUS
EFIAPI
UefiMain (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
Print (L"Hello World\n");
return EFI_SUCCESS;
}
在包级 .dsc 文件的 [Components] 段添加以下条目以注册该模块(以 OvmfPkg 为例):
OvmfPkg/HelloWorld/HelloWorld.inf
同时创建模块描述文件 HelloWorld.inf:
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = HelloWorld
FILE_GUID = 8D0E2C1A-2F5E-4B7A-9C3D-6E8F1A2B4C5D
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
ENTRY_POINT = UefiMain
[Sources]
HelloWorld.c
[Packages]
MdePkg/MdePkg.dec
[LibraryClasses]
UefiApplicationEntryPoint
UefiLib
编译与运行
- 在EDK2根目录执行
build -p OvmfPkg/OvmfPkgX64.dsc -m OvmfPkg/HelloWorld/HelloWorld.inf(或对应包名)。 - 编译产物位于
Build/OvmfX64/DEBUG_GCC5/X64/HelloWorld.efi(路径随工具链与架构变化)。 - 将
HelloWorld.efi复制到UEFI Shell可访问的FAT分区,或直接放入OVMF启动盘镜像。 - 在UEFI Shell中切换到文件所在文件系统(如
fs0:),执行HelloWorld.efi。
验证方法
运行后屏幕输出 Hello World 并返回Shell提示符,即表示应用编译正确、入口点被固件正常调用、Print 库函数工作正常。若在OVMF(QEMU)中运行,Shell窗口出现上述输出即为通过。
常见问题
- 编译报错“无法打开库文件”:检查
.inf中[LibraryClasses]是否包含UefiApplicationEntryPoint和UefiLib。 - 运行后无输出:确认
.efi文件确实从FAT分区加载,且Shell当前目录正确。 - GUID冲突:每个模块的
FILE_GUID必须唯一,可使用uuidgen生成新值。