4. UEFI应用退出与返回

任务目标

编写一个UEFI应用程序,调用gBS->Exit()退出启动服务并返回固件。该应用在入口点执行后立即退出,返回码为EFI_SUCCESS,用于验证UEFI应用从启动服务环境正确返回固件的过程。

实现原理

UEFI应用通过固件分配的入口点被加载执行。应用可通过系统表EFI_SYSTEM_TABLE中的BootServices指针调用Exit()主动终止自身。调用后控制权交还固件,固件继续执行后续启动策略(如加载下一启动项或进入Shell)。本案例仅演示退出流程本身,不涉及资源清理或额外功能。

完整代码

#include <Uefi.h>

EFI_STATUS
EFIAPI
UefiMain (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  // 直接通过启动服务退出,返回EFI_SUCCESS
  return SystemTable->BootServices->Exit (
           ImageHandle,          // 当前应用句柄
           EFI_SUCCESS,          // 退出码
           0,                    // ExitDataSize
           NULL                  // ExitData
           );
}

编译与运行

  1. 环境准备:安装EDK II开发环境,配置好WORKSPACE、PACKAGES_PATH等环境变量。
  2. 创建工程:在AppPkg/Applications/ExitDemo/下创建ExitDemo.inf文件:
[Defines]
  INF_VERSION     = 0x00010006
  BASE_NAME       = ExitDemo
  FILE_GUID       = 9E4F5A21-3D6C-4B8A-9F2E-7C1D5A8B4E62
  MODULE_TYPE     = UEFI_APPLICATION
  ENTRY_POINT     = UefiMain

[Sources]
  ExitDemo.c

[Packages]
  MdePkg/MdePkg.dec

[LibraryClasses]
  UefiApplicationEntryPoint
  1. 编译:在EDK II构建环境中执行:
build -p AppPkg/AppPkg.dsc -m AppPkg/Applications/ExitDemo/ExitDemo.inf
  1. 运行:将生成的ExitDemo.efi复制到UEFI启动介质(如FAT32格式的U盘或QEMU虚拟磁盘),在UEFI Shell中执行:
fs0:\> ExitDemo.efi

验证方法

  • 预期行为:应用执行后立即退出,Shell提示符重新出现,无任何输出信息。
  • 通过条件:Shell返回提示符且无错误信息,说明Exit()调用成功,应用已正确返回固件。若在调试器中运行,可观察到Exit()被调用后控制权回到固件Shell。
  • 返回码验证:在Shell中执行echo %lasterror%,若显示Success(或0x0),则确认退出码为EFI_SUCCESS。

常见问题

  • 编译失败:确认MODULE_TYPE为UEFI_APPLICATION且链接了UefiApplicationEntryPoint库。
  • 无法在Shell中运行:确认.efi文件位于可访问的文件系统且格式正确(FAT32)。
  • 退出后系统重启:若Exit()返回而非真正退出,通常是因为入口点返回值未被正确处理。本案例直接调用Exit(),固件应接管控制权;若固件实现有缺陷,可改用return EFI_SUCCESS作为备选方案(但本案例目标是验证Exit()路径)。