3. 使用UEFI控制台输出
任务目标
本案例将编写一个独立的UEFI应用程序,通过标准控制台协议ConOut输出格式化字符串,并演示文本前景色与背景色的设置方法。程序启动后依次输出默认颜色文本、彩色文本,最后恢复默认颜色并等待用户按键退出。
环境与依赖
- EDK2开发环境(版本不限,推荐最新稳定版)
- 已配置好
OVMF或真实UEFI固件作为运行目标 - 使用
QEMU虚拟机验证时,需安装qemu-system-x86_64
核心实现
以下代码为完整的UEFI应用程序入口,直接使用gST->ConOut协议完成输出与颜色控制。颜色属性值采用UEFI规范定义的EFI_TEXT_ATTR宏组合前景色与背景色。
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/UefiBootServicesTableLib.h>
EFI_STATUS
EFIAPI
UefiMain (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;
UINTN OriginalAttribute;
ConOut = SystemTable->ConOut;
// 保存当前颜色属性,便于退出时恢复
OriginalAttribute = ConOut->Mode->Attribute;
// 1. 默认颜色输出
ConOut->OutputString (ConOut, L"Hello UEFI Console!\r\n");
ConOut->OutputString (ConOut, L"Default color text.\r\n\r\n");
// 2. 设置前景色为红色,背景色为黑色
ConOut->SetAttribute (ConOut, EFI_TEXT_ATTR (EFI_RED, EFI_BLACK));
ConOut->OutputString (ConOut, L"Red foreground text.\r\n");
// 3. 设置前景色为绿色,背景色为黑色
ConOut->SetAttribute (ConOut, EFI_TEXT_ATTR (EFI_GREEN, EFI_BLACK));
ConOut->OutputString (ConOut, L"Green foreground text.\r\n");
// 4. 设置前景色为白色,背景色为蓝色
ConOut->SetAttribute (ConOut, EFI_TEXT_ATTR (EFI_WHITE, EFI_BLUE));
ConOut->OutputString (ConOut, L"White on blue background.\r\n\r\n");
// 5. 恢复默认颜色并提示退出
ConOut->SetAttribute (ConOut, OriginalAttribute);
ConOut->OutputString (ConOut, L"Press any key to exit...\r\n");
// 等待按键,避免程序立即退出导致看不到输出
SystemTable->ConIn->Reset (SystemTable->ConIn, FALSE);
{
EFI_INPUT_KEY Key;
EFI_STATUS Status;
do {
Status = SystemTable->ConIn->ReadKeyStroke (SystemTable->ConIn, &Key);
} while (Status == EFI_NOT_READY);
}
return EFI_SUCCESS;
}
构建与运行
- 将上述代码保存为
ConsoleOutput.c,放入EDK2工程目录(如UefiLessonsPkg/ConsoleOutput/)。 - 在对应
.inf文件中声明UefiMain为入口函数,并链接UefiLib与UefiBootServicesTableLib。 - 使用
build命令编译生成ConsoleOutput.efi。 - 运行QEMU并进入UEFI Shell,执行:
fs0:\> ConsoleOutput.efi
验证方法
- 程序启动后,第一行应为默认颜色的
Hello UEFI Console!。 - 随后依次出现红色、绿色文本,以及白字蓝底的文本行。
- 最后一行提示按键退出,颜色恢复为默认。
- 按任意键后程序返回Shell提示符,无报错信息。
上图展示了程序运行时的预期输出效果。颜色值定义在UefiSpec.h中,EFI_TEXT_ATTR(fg, bg)宏将前景色与背景色编码为单个属性值,SetAttribute接口在设置后立即生效,影响后续所有输出字符。