Understanding the UEFI Graphics Output Protocol

The Graphics Output Protocol (GOP) is the standard display mechanism within the Unified Extensible Firmware Interface (UEFI) environment, replacing legacy BIOS VGA and VESA BIOS Extensions. This article details what GOP is, how it operates in modern firmware, and the step-by-step process UEFI applications use to locate the protocol, configure display resolutions, and render pixels directly to a physical screen.

What is the Graphics Output Protocol?

The Graphics Output Protocol (GOP) is a UEFI boot-services protocol that provides a runtime-independent, hardware-agnostic interface for rendering graphics. In legacy BIOS systems, bootloaders and early-stage software relied on 16-bit real-mode interrupts (such as INT 10h) and VESA BIOS Extensions (VBE) to display graphics. GOP modernizes this by running in protected or long mode (32-bit or 64-bit), offering direct access to a linear framebuffer and high-resolution display modes without requiring specialized GPU drivers.

GOP remains active only during the UEFI boot phase. Once an operating system calls ExitBootServices(), control of the display hardware transitions away from UEFI GOP to native OS-level graphics device drivers.

How UEFI Applications Locate GOP

A UEFI application interacts with GOP through the UEFI Boot Services table. To initialize graphics:

  1. Locate the Protocol: The application calls gBS->LocateProtocol() or gBS->HandleProtocol(), passing the unique GUID for the Graphics Output Protocol (EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID).
  2. Obtain the Interface Pointer: Firmware returns a pointer to an EFI_GRAPHICS_OUTPUT_PROTOCOL structure containing pointers to protocol functions and display mode metadata.
EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop;
EFI_GUID GopGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;

EFI_STATUS Status = gBS->LocateProtocol(&GopGuid, NULL, (VOID**)&Gop);

Querying and Setting Display Modes

The GOP structure contains a Mode pointer, which houses the current display configuration:

  • MaxMode: The total number of video modes supported by the hardware.
  • Mode: The index of the currently active video mode.
  • Info: An EFI_GRAPHICS_OUTPUT_MODE_INFORMATION structure containing horizontal and vertical resolution, the pixel format, and the number of pixels per scanline.

If the default resolution is unsuitable, the application can enumerate modes by passing mode indices to Gop->QueryMode(). Once the desired resolution is identified, the application applies it by calling Gop->SetMode().

How Pixels Are Drawn to the Screen

UEFI applications draw pixels to the screen using one of two primary methods: direct linear framebuffer access or the Block Transfer (Blt) function.

Method 1: Writing Directly to the Linear Framebuffer

The most common approach for performance-sensitive tasks, such as custom bootloaders or early GUI rendering, is writing directly to video memory.

  1. Get the Base Address: The physical memory address of the display buffer is exposed at Gop->Mode->FrameBufferBase.
  2. Determine Pixel Format: The Info->PixelFormat field indicates the byte ordering, commonly PixelBlueGreenRedReserved8BitPerColor (BGRA) or PixelRedGreenBlueReserved8BitPerColor (RGBA), with 32 bits (4 bytes) per pixel.
  3. Calculate the Pixel Offset: Due to hardware alignment, display rows often include padding. Applications must use PixelsPerScanLine rather than HorizontalResolution to calculate memory offsets:

\[\text{Offset} = (Y \times \text{PixelsPerScanLine} + X) \times 4\]

  1. Write the Color Value: The application writes the 32-bit color data directly to the memory address:
UINT32 *Framebuffer = (UINT32*)Gop->Mode->FrameBufferBase;
UINT32 Index = (Y * Gop->Mode->Info->PixelsPerScanLine) + X;

// Write a 32-bit color value (e.g., Red in a 0x00RRGGBB/BGR format depending on layout)
Framebuffer[Index] = 0x00FF0000;

Method 2: The Block Transfer (Blt) Function

GOP also provides a built-in software blit service via Gop->Blt(). This function allows the application to manipulate rectangular regions of the screen without manually writing to the framebuffer.

The Blt function supports several operations via the EFI_GRAPHICS_OUTPUT_BLT_OPERATION enum:

  • EfiBltVideoFill: Fills a specified rectangular area on the screen with a single solid color.
  • EfiBltBufferToVideo: Copies pixel data from a system memory buffer onto the display.
  • EfiBltVideoToBltBuffer: Reads a rectangular area of pixels from the display back into system memory.
  • EfiBltVideoToVideo: Copies a rectangle from one location on the screen directly to another, useful for scrolling console text.

Using direct framebuffer writes provides faster rendering for dynamic graphics, whereas Blt offers a simple, standardized abstraction for basic UI drawing and buffer swapping.