BIOS开发笔记 21 – RGRT Logo
一、什么是BGRT?
-
LOGO图像数据存储在内存的什么位置 -
图像显示在屏幕的哪个位置 -
图像当前的显示状态
这样操作系统启动时可以无缝延续显示这个LOGO,避免屏幕闪烁或黑屏,实现从固件到操作系统的平滑视觉过渡。
签名标识:'B' 'G' 'R' 'T'
二、BGRT表结构
2.1 完整结构定义
根据ACPI规范,BGRT表结构如下:
typedef struct {
EFI_ACPI_DESCRIPTION_HEADER Header; // ACPI标准表头
UINT16 Version; // 版本号
UINT8 Status; // 状态字段
UINT8 ImageType; // 图像类型
UINT64 ImageAddress; // 图像物理地址
UINT32 ImageOffsetX; // X坐标偏移
UINT32 ImageOffsetY; // Y坐标偏移
} EFI_ACPI_6_5_BOOT_GRAPHICS_RESOURCE_TABLE;
2.2 BGRT特定字段
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2.3 Status字段详解
Bit[0] : Displayed 0 = 图像未显示或显示已被中断 1 = 图像当前正在显示 Bits[2:1] : Orientation Offset (顺时针旋转角度) [00] = 0度 (默认方向) [01] = 90度 [10] = 180度 [11] = 270度 Bits[7:3] : Reserved (保留,必须为0)
Status字段的使用场景:
-
• 当用户进入BIOS Setup界面时,应将Bit[0]清零,表示图像显示已中断 -
• 操作系统检测到此位为0时,不会尝试延续显示LOGO -
• 支持屏幕旋转的设备可使用Bits[2:1]指示旋转角度(如常见的竖屏平板,通过BIOS旋转为横屏)
2.4 ImageType字段
0 = Bitmap (BMP格式) 1-255 = Reserved (保留供将来使用)
目前ACPI规范只定义了BMP格式支持。
三、实现流程
3.1 总体流程
步骤0: 系统启动 (Boot Process) ↓ 步骤1: 初始化图形设备 GOP/UGA • 设置合适的显示模式 • 获取屏幕分辨率 ↓ 步骤2: 加载并绘制启动LOGO • 从固件存储加载图像 • 转换为帧缓冲格式 • 计算显示位置并绘制 • 记录显示坐标 ↓ 步骤3: 从显存提取LOGO图像 • 读取LOGO区域像素数据 • 转换为24位BMP格式 • 分配内存存储BMP数据 ↓ 步骤4: 构建BGRT表 • 填充ACPI表头 • 设置 Version=1, Status=1 • 设置 ImageType=0 (BMP) • 设置 ImageAddress • 设置显示坐标 • 计算校验和 ↓ 步骤5: 注册到ACPI • 通过ACPI Table Protocol安装 • 保存表句柄供后续更新 ↓ 步骤6: 操作系统接管 • 读取BGRT表 • 延续显示LOGO直到启动完成
3.2 关键实现步骤
步骤1:获取图形输出协议
EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop; gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&Gop); UINT32 Width = Gop->Mode->Info->HorizontalResolution; UINT32 Height = Gop->Mode->Info->VerticalResolution;
步骤2:计算LOGO显示位置
水平居中,垂直方向按黄金比例(38.2%)定位:
INT32 DestX = (ScreenX - LogoWidth) / 2; // 水平居中 INT32 DestY = (ScreenY * 382 / 1000) - (LogoHeight / 2); // 垂直38.2%
步骤3:从显存提取图像
EFI_UGA_PIXEL *BltBuffer = AllocatePool(LogoWidth * LogoHeight * sizeof(EFI_UGA_PIXEL)); Gop->Blt(Gop, BltBuffer, EfiBltVideoToBltBuffer, DestX, DestY, 0, 0, LogoWidth, LogoHeight, 0);
步骤4:转换为BMP格式
关键点:4字节行对齐、BGR顺序、从下到上存储:
UINT32 RowSize = (Width * 3 + 3) & ~3; // 行字节数(4字节对齐) UINT8 *BmpData = AllocatePool(54 + RowSize * Height); // 填充BMP头(54字节): 签名'BM', 24位色深, 无压缩 // 写入像素: 从下到上, BGR顺序, 行末填充对齐
步骤5:构建BGRT表
Table->Version = 1; Table->Status = 1; // 已显示 Table->ImageType = 0; // BMP格式 Table->ImageAddress = (UINT64)BmpData; // 图像地址 Table->ImageOffsetX = DestX; // X坐标 Table->ImageOffsetY = DestY; // Y坐标 Table->Header.Checksum = CalculateChecksum(); // 计算校验和
步骤6:安装到ACPI
EFI_ACPI_TABLE_PROTOCOL *AcpiTable; gBS->LocateProtocol(&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTable); AcpiTable->InstallAcpiTable(AcpiTable, BgrtTable, TableSize, &TableKey);
四、状态管理
4.1 进入Setup界面
当用户按键进入BIOS Setup时,需要将Status字段清零:
BgrtTable->Status &= ~0x01; // 清除Displayed位 BgrtTable->Header.Checksum = CalculateChecksum(BgrtTable); // 重算校验和 AcpiTable->InstallAcpiTable(AcpiTable, BgrtTable, Size, &Key); // 重装ACPI表
4.2 Legacy Boot
Legacy BIOS启动时不支持BGRT,应在启动前卸载:
AcpiTable->UninstallAcpiTable(AcpiTable, TableKey);
4.3 动画LOGO处理
如果启动LOGO是动画(如GIF),BGRT应标记为未显示:
BgrtTable->Status = 0; // 不标记为已显示 // 操作系统将不会尝试延续显示动画帧
五、内存管理注意事项
5.1 内存分配策略
-
• BMP数据缓冲区:必须在操作系统可访问的物理内存中分配 -
• 内存类型:必须使用 EfiRuntimeServicesData -
• 地址要求:ImageAddress存储的是物理地址
5.2 内存生命周期
步骤1: 分配BMP缓冲区 (使用ACPI可访问内存类型) ↓ 步骤2: 转换图像数据 (从帧缓冲读取并转换) ↓ 步骤3: 注册BGRT表 (ACPI Table Protocol) ↓ 步骤4: 保持内存有效 (不要释放,留给OS使用) ↓ 步骤5: 操作系统读取
重要:BGRT引用的图像数据内存不能在Boot Services退出前释放,操作系统需要在启动过程中访问这些数据。
版权声明:
作者:bin
链接:https://ay123.net/mystudy/1956/
来源:爱影博客
文章版权归作者所有,未经允许请勿转载。
THE END
0
二维码
海报
BIOS开发笔记 21 – RGRT Logo
一、什么是BGRT?
BGRT(Boot Graphics Resource Table)是ACPI 5.0规范引入的一个ACPI表,其核心目的是实现从BIOS/UEFI启动阶段到操作系统的无缝视觉过渡。……
文章目录
关闭
共有 0 条评论