12.9 Graphics Output Protocol(GOP)
来源:UEFI Specification 2.11 · 第 12 章 Protocols — Console Support · 12.9 节
12.9.1 EFI_GRAPHICS_OUTPUT_PROTOCOL
GOP 是 UEFI 图形控制台的基础协议,为图形输出设备提供视频模式设置、帧缓冲访问与像素拷贝(Blt) 能力,取代了旧式 VGA/UGA 方案。每个帧缓冲对应一个 GOP 实例;一个视频控制器可产生多个 GOP(多输出适配器),每个活动输出 handle 上同时安装 GOP、EDID Discovered 与 EDID Active 协议。
- GUID:
9042A9DE-23DC-4A38-96FB-7ADED080516A - 协议结构:
typedef struct _EFI_GRAPHICS_OUTPUT_PROTOCOL {
EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE QueryMode; // 12.9.2.1
EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE SetMode; // 12.9.2.2
EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT Blt; // 12.9.2.3
EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode; // 12.9.2.4
} EFI_GRAPHICS_OUTPUT_PROTOCOL;
相关类型定义(属于 12.9.1):
// 32-bit 像素:B、G、R、保留(0~255)
typedef struct {
UINT8 Blue;
UINT8 Green;
UINT8 Red;
UINT8 Reserved;
} EFI_GRAPHICS_OUTPUT_BLT_PIXEL;
// Blt 操作类型
typedef enum {
EfiBltVideoFill, // 0:用 BltBuffer[0] 填充目标矩形(忽略源坐标与 Delta)
EfiBltVideoToBltBuffer, // 1:屏幕矩形 → CPU 缓冲(DestX/Y 指向缓冲;非零需 Delta)
EfiBltBufferToVideo, // 2:CPU 缓冲 → 屏幕矩形(SourceX/Y 指向缓冲;非零需 Delta)
EfiBltVideoToVideo, // 3:帧缓冲内矩形拷贝(忽略 BltBuffer 与 Delta,允许重叠)
EfiGraphicsOutputBltOperationMax
} EFI_GRAPHICS_OUTPUT_BLT_OPERATION;
12.9.2 服务函数与数据结构
12.9.2.1 EFI_GRAPHICS_OUTPUT_PROTOCOL.QueryMode()
返回某个模式号(ModeNumber)下,图形设备与活动输出设备共同支持的模式信息。
typedef
EFI_STATUS
(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE)(
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
IN UINT32 ModeNumber,
OUT UINTN *SizeOfInfo,
OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
);
ModeNumber:0 ~ MaxMode-1;未设置过模式(Mode 未初始化)时先调用 SetMode(),否则返回EFI_NOT_STARTEDSizeOfInfo/Info:callee 分配的缓冲区大小与指针- 返回:
EFI_SUCCESS、EFI_DEVICE_ERROR、EFI_UNSUPPORTED、EFI_INVALID_PARAMETER、EFI_BUFFER_TOO_SMALL、EFI_NOT_STARTED
12.9.2.2 EFI_GRAPHICS_OUTPUT_PROTOCOL.SetMode()
将视频设备设为指定模式,并把输出显示可见区域清为黑色。
typedef
EFI_STATUS
(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE)(
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
IN UINT32 ModeNumber
);
- 返回:
EFI_SUCCESS、EFI_DEVICE_ERROR、EFI_UNSUPPORTED、EFI_INVALID_PARAMETER
12.9.2.3 EFI_GRAPHICS_OUTPUT_PROTOCOL.Blt()
在帧缓冲与 Blt 缓冲之间进行块传输的软件抽象,共 4 种操作(见 12.9.1 的 EFI_GRAPHICS_OUTPUT_BLT_OPERATION)。
typedef
EFI_STATUS
(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT)(
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, // OPTIONAL
IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
IN UINTN SourceX,
IN UINTN SourceY,
IN UINTN DestinationX,
IN UINTN DestinationY,
IN UINTN Width,
IN UINTN Height,
IN UINTN Delta // OPTIONAL
);
Delta:Blt 缓冲每行字节数(拷贝模式且 (X,Y) 非零时必需);为 0 时以 Width 作为行宽- 屏幕原点 (0,0) 在左上角
- 返回:
EFI_SUCCESS、EFI_INVALID_PARAMETER、EFI_DEVICE_ERROR、EFI_UNSUPPORTED
12.9.2.4 EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
当前图形输出设备模式信息:
typedef struct {
UINT32 MaxMode; // QueryMode()/SetMode() 支持的模式数
UINT32 Mode; // 当前模式号(0 ~ MaxMode-1)
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; // 只读模式信息指针
UINTN SizeOfInfo; // Info 结构字节数(后续版本可能增大)
EFI_PHYSICAL_ADDRESS FrameBufferBase; // 线性帧缓冲基址(偏移 0 = 左上角像素)
UINTN FrameBufferSize; // 帧缓冲大小 = PixelsPerScanLine × VerticalResolution × 每像素字节
} EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE;
12.9.2.5 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
描述一个图形输出模式:
typedef struct {
UINT32 Version; // 结构版本
UINT32 HorizontalResolution; // X 方向像素数
UINT32 VerticalResolution; // Y 方向像素数
EFI_GRAPHICS_PIXEL_FORMAT PixelFormat; // 像素物理格式
EFI_PIXEL_BITMASK PixelInformation; // 仅 PixelBitMask 格式有效
UINT32 PixelsPerScanLine; // 每行像素数(pitch)
} EFI_GRAPHICS_OUTPUT_MODE_INFORMATION;
行字节数(pitch)= PixelsPerScanLine × 每像素字节数;帧缓冲内像素偏移 = pitch×y + 每像素字节数×x
12.9.2.6 EFI_GRAPHICS_PIXEL_FORMAT
typedef enum {
PixelRedGreenBlueReserved8BitPerColor, // 0:RGBX
PixelBlueGreenRedReserved8BitPerColor, // 1:BGRX(多数硬件默认)
PixelBitMask, // 2:由 EFI_PIXEL_BITMASK 定义
PixelBltOnly, // 3:无线性帧缓冲,仅能用 Blt() 绘制
PixelFormatMax
} EFI_GRAPHICS_PIXEL_FORMAT;
12.9.2.7 EFI_PIXEL_BITMASK
typedef struct {
UINT32 RedMask;
UINT32 GreenMask;
UINT32 BlueMask;
UINT32 ReservedMask;
} EFI_PIXEL_BITMASK;
关键要点(GOP driver 研究)
- 使用流程:
LocateProtocol(&gEfiGraphicsOutputProtocolGuid) → 若Mode 未初始化先SetMode(0) → 遍历QueryMode() 选择模式 →SetMode(n) → 直接写FrameBufferBase 或调用Blt() - GOP 是 Boot Time 服务,
ExitBootServices()后协议不可用,但帧缓冲保留,可在 OS 中继续使用 - 写像素前先按
PixelFormat 判断像素布局(RGBX / BGRX / BitMask);PixelBltOnly无帧缓冲 - 图形驱动需在活动输出 handle 上同时安装 EDID Discovered/Active 协议;平台若提供 EDID Override 协议,驱动必须优先使用其数据填充 EDID Active
EDID 三协议机制(Discovered / Override / Active)
依据:UEFI 规范 12.9 节、Intel《UEFI Driver Development Guide for Graphics Controller Device Classes》、tianocore《UEFI Driver Writer’s Guide》第 23 章
角色分工:
| 协议 | 角色 | 数据来源 |
|---|---|---|
| EFI_EDID_DISCOVERED_PROTOCOL | 从视频输出设备实际读取到的原始 EDID(事实数据) | 硬件 DDC/I²C 通道 |
| EFI_EDID_OVERRIDE_PROTOCOL(平台可选) | 平台固件提供的覆盖策略(强制分辨率、EDID 修正等) | 平台/用户配置 |
| EFI_EDID_ACTIVE_PROTOCOL | 最终生效的 EDID,系统据此决定显示能力 | Discovered 或 Override 之一 |
数据链路:
硬件读到的 EDID (Discovered) ──┬─► 无 Override ──► EDID Active
└─► 有 Override ──► 用 Override 数据填充 EDID Active
为什么必须同时安装 Discovered + Active:
- 两个协议承载两个语义:硬件原始能力(Discovered)与系统最终配置(Active),Override 机制依赖二者区分才成立
- 消费者不同:系统固件/OS Loader 只看 Active(最终生效);调试诊断看 Discovered(未被策略污染)
- 规范硬性要求:
EFI_EDID_DISCOVERED_PROTOCOL must exist on each handle that represents a video output, and must only represent a single video output device - 每个输出 child handle 缺一不可,否则不构成完整的"输出设备接口"
与 GOP 的协作(驱动实现顺序):
Start()枚举图形控制器输出端口 → 每个输出创建 child handle- 读取硬件 EDID → 安装 EDID Discovered
- 查询平台 EDID Override → 决定数据源 → 安装 EDID Active
- 计算 控制器支持的模式 ∩ 显示器(EDID)支持的模式 → 安装 GOP(
MaxMode 与QueryMode()返回的都是该交集)
类比:Discovered = 显示器铭牌参数(出厂事实);Override = 贴的便签"实际按 1080p 用"(平台策略);Active = 系统最终照做的参数。只有铭牌无法执行,只有执行参数无法回溯真实能力,故规范要求两个都装。

392

被折叠的 条评论
为什么被折叠?



