VBE (VESA BIOS Extension) is an industry standard that allows software in real or protected mode to access the video card without direct register access, enabling arbitrary resolutions and color depths beyond standard VGA.
VBE was actively used in operating system bootloaders (e.g., early Linux, LILO), DOS console games, and x86 embedded systems. It was also used in BIOS Setup and low-level diagnostic utilities before initializing a full graphics driver.
Typical problems
Main issues are related to incorrect bank switching functions (windowed framebuffer) in non-linear modes, causing artifacts. Another problem is address space conflicts when working with other BIOS extensions. On modern systems, VBE support is absent in UEFI, replaced by GOP.
How it works
VBE is implemented as a set of subfunctions called via software interrupt INT 10h with a specific value in register AX (e.g., 4F00h to get information). Unlike standard VGA, which is tightly bound to ports 3C0h-3DAh and fixed video modes (13h – 320x200x256), VBE dynamically queries the video card for a list of supported modes via memory data structures. The key difference from the linear framebuffer used in modern drivers (e.g., addressing via PCI BAR) is the windowed access mechanism: when video memory exceeds 64KB and there is no common available range in segment A0000h, VBE uses function 4F05h (Set/Get Window) – software-switchable 64KB windows into video memory. At the same time, VBE 3.0 introduced Linear Frame Buffer (LFB) support, operating through a single contiguous memory space at higher addresses (Ext8M), making it fundamentally similar to protected mode methods. Unlike hardware accelerators (OpenGL, DirectX), VBE does not accelerate operations – it only standardizes access to basic output functions and controller operating modes.
VESA BIOS functionality description
- Video memory modes. VESA BIOS provides an interface to switch video modes beyond standard VGA resolutions. Functions
0x4F02and0x4F03set and read the mode with arbitrary frame geometry. The mode is specified by a 16-bit identifier including linear buffer bits (bit 14). - Linear frame buffer. The LFB (Linear Frame Buffer) flag enables a 32-bit flat address space for video memory. Unlike banking (64KB windows), LFB is accessible via a single segment in protected mode. The buffer address is returned in the mode structure via call
0x4F01, allowing direct pixel access. - Adapter capability detection. Function
0x4F00returns a pointer to the VBE Info block. The block contains the VESA version, video memory size (in 64KB blocks), list of supported modes, and OEM string. The code checks for the VBE2 bit in the signature to confirm compatibility. - Mode information structure. Call
0x4F01fills the ModeInfoBlock (256 bytes). Fields include linear stride, color depth: number of planes, bits per pixel (8/15/16/24/32), mode attributes (windowed or linear access support). It also returns the physical LFB buffer address. - Alpha channel and pixel packing. For 32-bit modes, VBE defines the offset and size of each RGB/alpha component via fields RedMaskSize, RedFieldPosition, and similar for green, blue, and alpha. This allows working with non-standard byte orders (e.g., BGR or RGBA).
- Double buffering via bank windows. If LFB is unavailable (bit 0 in Attributes is clear), VBE allows setting a bank window (usually
A0000h,B8000h) via function0x4F05. Parameters: window 0 or 1, bank number (in 64KB steps). This is necessary for older adapters (SVGA pre-PCI). - SVGA (Generation of frame synchronization and raster scan)
- Getting current bank number. Function
0x4F05, when queried, returns the current active bank for both windows. This is sometimes needed to optimize switching during line-by-line output. Return bits reflect the actual controller state after hardware delays. - Protected mode and 32-bit access. VBE version 2.0 and later offers functions for 32-bit protected mode environment (Protect Mode Interface – PMI). Via
0x4F0A, a far pointer can be obtained to a vector table callable directly from flat memory model, bypassing real mode. - Palette and DAC controllers. For 8-bit per pixel indexed modes, VBE retains standard VGA functions (
INT 10h, AH=10h). However, the VBE extension allows changing palette size (up to 256 entries of 6 bits per component), as well as reading/setting DAC registers. - DirectColor formats. When the DirectColor mode attribute bit (bit 4 in ModeAttributes) is set, component masks are used instead of a palette. VBE explicitly specifies the number of bits for red, green, blue, and their offset within the pixel. This is critical for 15/16-bit modes (5:5:5, 5:6:5).
- Stride and alignment. The BytesPerScanLine field in ModeInfoBlock gives the actual number of bytes per line (always a multiple of 4 or 8 for LFB). When rendering graphics, note that the linear buffer pitch may be larger than width × bpp/8 due to hardware alignment.
- Save/restore state function. VBE 3.0 provides
0x4F04for managing video context. An action mask is passed: save/restore controller state, CRTC registers, DAC, and the entire video memory contents. The required buffer size is returned. - Switching between windowed and linear modes. When first selecting a mode via
0x4F02, you can request windowed access (bit 14 = 0) or LFB (bit 14 = 1). Some drivers switch access method on the fly by reinitializing the memory controller without changing resolution. - Determining video memory size. The VBE Info Block contains a TotalMemory field (in 64KB units). However, actual access to memory beyond the detected size causes failures. For reliability, use function
0x4F00and check the maximum visible line beyond standard queries. - Standard VESA mode numbers. The first hundred numbers (
0x100–0x17F) are defined by the specification: e.g.,0x101= 640×480×8,0x110= 640×480×16 (5:5:5). Vendor modes start at0x180. Always verify support via0x4F01, ignoring constants. - Atomicity of mode switching. Call
0x4F02must be performed in real mode with interrupts disabled (CLI) and stack restoration. Some BIOSes redefine vectors when changing refresh rates, requiring backup of VGA registers before the call. - Working with multiple monitors. VBE does not provide direct support for multi-head systems, but by selecting a video card (based on PCI, controlling IDSEL) and calling function
0x4F00with local BIOS segment memory, you can switch the active device. - Limitations in clock fractions. The HorizResolution and VertResolution fields in ModeInfoBlock are merely geometry. Actual pixel clock, sync pulse timings, and polarities are model-dependent; VBE does not manage modes limited by the monitor. Code must check support via DDC/CI separately.
- Errors and return codes. All VBE functions return
0x4Fin AL (or AX) on success. Errors:0x01(mode not supported),0x02(mode not working),0x03(call invalid),0x004F(function not implemented in current version). AH also duplicates the success flag (0x00). - Interaction with PCI configuration. For proper LFB mapping in protected mode, the physical video memory address (usually returned in PhysBasePtr) is required. It can also be obtained from BAR0 of the video card via PCI configuration space, but VBE should take priority.
Comparisons with other functions
- VESA BIOS vs VGA BIOS. VESA BIOS extends standard VGA BIOS by adding high-resolution and high-color mode support via Super VGA. VGA BIOS is limited to basic 640×480 16-color modes, while VESA BIOS can address up to 1600×1200 with 24 bits per pixel, but requires a compatible video card and driver.
- VESA BIOS vs DirectX (graphics APIs). VESA BIOS operates at a low level via software interrupts (
int 10h) and is suitable for DOS, providing portability without drivers. DirectX, on the other hand, provides hardware acceleration, buffering, and 3D functions in Windows but requires drivers and an OS, making VESA BIOS preferable for embedded systems. - VESA BIOS vs UEFI GOP. VESA BIOS uses interrupts and linear frame buffer in real mode, limiting access to 64KB of code. UEFI Graphics Output Protocol (GOP) replaces it in modern systems, operating in protected mode with 64-bit addressing, multitasking, and multi-monitor configuration support without VESA emulation.
- VESA BIOS vs Linux FBDev. VESA BIOS is a standardized OS-independent interface but is slow due to software framebuffer access via BIOS calls. Linux FrameBuffer Device (FBDev) provides direct video memory mapping into kernel address space, which is faster but requires a chipset-specific driver, whereas VESA BIOS works out of the box.
- FBDev (Outputting graphics via frame buffer device)
- VESA BIOS vs Vulkan/OpenGL. VESA BIOS deals with simple 2D pixel output without pipeline processing, sufficient for text modes and bootloaders. Vulkan and OpenGL provide full 3D graphics with shaders, depth buffers, and parallel processing but require complex multithreaded code and a full OS, where VESA BIOS only serves as initial output initialization.
OS and driver support
VBE is implemented via a 16-bit BIOS interface (interrupt 0x10, functions 0x4F00–0x4F0A), which requires 32/64-bit operating systems to switch to real mode using V86 (Virtual 8086 mode) or emulate BIOS calls (for example, via VBE 3.0 with protected mode providing a 32-bit CS:EIP interface). Drivers for Windows, Linux, and BSD use a linear frame buffer (LFB) and bank switching mode, while modern graphics drivers natively bypass VBE by loading their own mode through DirectX, DRI, or KMS.
Security
VBE has no built-in memory protection, access control, or buffer boundary checking, allowing calling code to write to the LFB or bank switching registers directly from real or protected mode, which leads to the possibility of arbitrary reading and writing of video memory (an MMIO-type access vulnerability) without permission checks. Operation in V86 mode on x86 can be used to break isolation (for example, through incorrect interrupt handling or erroneous returns from VBE functions) because there is no support for SMP, page protection, or ring protection for the extension itself.
Logging
VBE does not provide standard logging mechanisms at the BIOS level, but operating system drivers (such as vesafb in Linux) emulate this by intercepting VBE function calls 0x4F00–0x4F0A and logging their parameters (AH=0x4F, AL=subfunction number, ES:DI=pointer to the VBEInfo block) to the system log (dmesg, Windows event log) along with the return codes received (AH status 0x4F for success, AL=0x4F for failure). They also record failures when attempting to set an unsupported video mode or when LFB behaviour is incorrect. However, at the level of the VBE code in ROM, logging is absent except for some vendor-specific implementations (for example, Matrox or ATI) that output debug codes via port 0x80.
Limitations
VBE is limited to 64 MB of address space via banked access (functions 0x4F05–0x4F06 with a 64 KB window at A0000h–BFFFFh), slow performance when frequently switching banks (up to 10 thousand operations per second), support for only one monitor (primary graphics controller), lack of 2D/3D hardware acceleration (only framebuffer and palette), maximum resolution depending on implementation (typically 1600×1200×32bpp, but VBE 3.0 allows up to 1920×1440 and higher), no hardware cursor, no vertical synchronisation by default, and complete dependence on real mode (even VBE 3.0 Protected Mode Entry requires the kernel code to first switch the processor to real mode or use an intermediary transition into V86).
History and development
VBE was developed by VESA in 1989 (v1.0) to standardise SVGA access (800×600, 1024×768) across different manufacturers. VBE 2.0 (1994) added a linear frame buffer (LFB) and protected mode via the PMI interface. VBE 3.0 (1998) introduced support for 32-bit protected mode and limited multitasking, but with the widespread transition to UEFI and GOP (Graphics Output Protocol) in the 2000s, development of VBE ceased. Its emulation via CSM (Compatibility Support Module) in UEFI and drivers (efifb, simpledrm, vfio-mdev) is preserved only for legacy operating systems (DOS, Windows 9x, early Linux without KMS) and bootloaders (GRUB Legacy, LILO), turning VBE into a historical standard with minimal relevance in modern computing systems.