Introduction
Before permanently switching to protected mode and disabling BIOS services, the bootloader must establish a usable graphics environment. Historically, PC graphics evolved around two major standards: VGA and VESA BIOS Extensions (VBE).
These technologies form the foundation of video output in early computers and remain relevant today in boot processes and compatibility modes.
VGA provides basic, low-resolution graphics suitable for text consoles and early GUIs, while VBE extends VGA with higher resolutions, better color depth, and linear frame access. Modern kernels often still rely on VBE during early boot to initialize graphics before native drivers take over.
VGA (Video Graphics Array):
VGA was introduced by IBM in 1987 and became the de-facto graphics standard for DOS and early Windows systems.
Key characteristics:
- Low resolutions such as 320x200, 640x480
- Limited color depth (16 or 256 colors)
- Bank-switched video memory
- Simple BIOS programming model
VGA remains important for fallback and compatibility modes.
For more information, have a look at this article: https://thejat.in/learn/vga-in-real-mode
VESA BIOS Extensions (VBE) (Video Electronics Standards Association):
VBE was designed to overcome VGA limitations by providing a standardized BIOS interface for advanced video hardware.
VBE enables:
- Higher resolutions (800x600, 1024x768, 1280x720, 1920x1080, …)
- Higher color depths (15-bit, 16-bit, 24-bit, 32-bit)
- Linear Framebuffer (LFB) access
- Hardware-independent mode discovery
VESA (Video Electronics Standards Association) functions, specifically referring to VESA BIOS Extensions (VBE), provide a standardized interface for software to interact with graphics hardware.
For more information explore this article: https://thejat.in/learn/vesa-bios-extensions-vbe
VBE Programming Model
All VBE functionality is exposed through INT 10h with function numbers in the 0x4Fxx range.
Typical workflow:
- Query VBE controller capabilities (4F00h)
- Retrieve supported video mode list
- Query each mode's properties (4F01h)
- Select the best mode
- Activate the chosen mode (4F02h)
VBE Functions:
VBE got a lot of functions which we can use to get general information about hardware, supported video modes, setting a particular video modes and a lot more. We will explore some of them here.
1️⃣ Get VBE Controller Information (INT 10h, AX=4F00h) GetVbeInfo:
Function Purpose:
Retrieves general VBE implementation details and obtain a pointer to the supported video mode list.
Function Prototype:
Function: GetVbeInfo
Input: AX = 4F00h
ES:DI = Pointer to a buffer (VBEInfoBlock)
512 bytes data structure
Output: VBEInfoBlock filled with VBE information
Return: AX = VBE Status (Success or Error Code)
AL = 4Fh - If the function is supported
AH = 00h - Function successful
Usage:
- Description: The
GetVbeInfofunction is used to query the system's VBE capabilities and configuration details. - Input: Set AX to 4F00h to indicate the request for VBE information.
- Output: The function populates a structure (
VBEInfoBlock) pointed to by ES with detailed information such as VBE version, supported video modes, display memory information, and capabilities. - Return Value: AX upon return contains a status code indicating success (00h) or an error code if the function fails.
VBE Controller Info Structure
struc VbeControllerStruct
.Signature resb 4
.Version resw 1
.OemNamePtr resd 1
.Capabilities resd 1
.ModeListPtr resd 1
.Num64KBlocksMem resw 1
.Reserved resb 492
endstrucThis ModeListPtr field is the most important – it points to a list of 16-bit video mode IDs terminated by 0xFFFF.
Here is the complete code:
vesa.inc:
Defining the structure and initialization of the structure
First we will define the structure where our data will be stored:
; Structure Definitions
struc VbeControllerStruct
.Signature resb 4
.Version resw 1
.OemNamePtr resd 1
.Capabilities resd 1
.ModeListPtr resd 1 ; List of WORDS terminated by 0xFFFF
.Num64KBlocksMem resw 1
.ReservedSpace resb 492
endstruc
; ****************************
; VBE Structures, initialization
; ****************************
VesaControllerInfo:
istruc VbeControllerStruct
at VbeControllerStruct.Signature, db 0, 0, 0, 0
at VbeControllerStruct.Version, dw 0
at VbeControllerStruct.OemNamePtr, dd 0
at VbeControllerStruct.Capabilities, dd 0
at VbeControllerStruct.ModeListPtr, dd 0 ; List of WORDS terminated by 0xFFFF
at VbeControllerStruct.Num64KBlocksMem, dw 0
at VbeControllerStruct.ReservedSpace, times 492 db 0
iendCall the interrupt
; Setup buffer
xor eax, eax
xor edi, edi
mov es, ax
mov edi, VesaControllerInfo ; The area where bios information will
; be stored
; Get Controller Info, 0x4f00
call VesaControllerInfo
test eax, eax
jne .Fail
; **************************
; VesaGetVideoModes
; IN:
; - ES:DI: Buffer
; OUT:
; - EAX: 0 for success
; **************************
VesaGetVideoModes:
; Save state
pushad
; Setup for INT
xor eax, eax
mov ax, 0x4F00
int 0x10
; Check if success
test ah, ah
jne .NoVesa
cmp al, 0x4F
jne .NoVesa
; game on.
popad
;; Store the VBE Controller Info address for future references.
mov dword [BootHeader + MultiBoot.VBEControllerInfo], edi
mov eax, 0
ret
; old school system
.NoVesa:
popad
mov eax, 1
retFrom this function we got the address where the list of video mode id's is stored which is at address pointed by the VesaControllerInfo + VbeControllerStruct.ModeListPtr. This ModeListPtr is pointing to the all the video mode id list supported by the graphics card. Now we need to parse this list by using this address.
We will use this address and every list at this address is of word (16-bit) in size means first 16-bit contains the first video mode id, then next 16-bit contains the second video mode id, and 0xFFFF denotes the end of the list. We will pass these id in a loop to the next function 0x4f01 to get information about video mode by its id and read it in a buffer.
2️⃣ GetVideoModeList
Function Purpose: Retrieves a list of supported video modes by querying the VBE. The VBE function 4F01h is used to retrieve detailed information about a specific video mode supported by the VESA BIOS Extensions (VBE). This function provides detailed information such as resolution, color depth, and other characteristics of a particular video mode.
Function Prototype:
Function: GetVideoModeList
Input: AX = 4F01h
CX = Video mode index (0-based, start with 0)
ES:DI = Pointer to a buffer (ModeInfoBlock)
Output: ModeInfoBlock filled with video mode information
256 bytes in size.
Return: AX = VBE Status (Success or Error Code)
Usage:
- Description: The
GetVideoModeListfunction allows software to obtain a list of supported video modes from the VBE. - Input: Set AX to 4F01h to indicate the request for video mode information. Set CX to the index of the video mode to query (starting from 0).
- Output: The function fills a structure (
ModeInfoBlock) pointed to by ES with details about the specified video mode, including resolution, color depth, memory layout, and other characteristics. - Return Value: AX upon return indicates the status of the operation—success (00h) or an error code if the function fails.
Code:
First we define a structure for reading the video mode information, we can use memory buffer as well. However reading at particular offset is easy in structure by just using the name as the offset rather than using immediate value in case of memory buffer.
;; Definition
struc VbeModeStruct
.Attributes resw 1
.WindowAttribsA resb 1
.WindowAttribsB resb 1
.WindowGranKb resw 1
.WindowSizeKb resw 1
.WindowASegment resw 1
.WindowBSegment resw 1
.FuncPtrPosition resd 1
.BytesPerScanline resw 1
.ResolutionX resw 1
.ResolutionY resw 1
.CharCellWidth resb 1
.CharCellHeight resb 1
.NumPlanes resb 1
.Bpp resb 1
.NumBanks resb 1
.MemoryModel resb 1
.BankSizeKb resb 1
.MaxImagePages resb 1
.Reserved resb 1
.RedMaskSize resb 1
.RedFieldPos resb 1
.GreenMaskSize resb 1
.GreenFieldPos resb 1
.BlueMaskSize resb 1
.BlueFieldPos resb 1
.AlphaMaskSize resb 1
.AlphaFieldPos resb 1
.DirectColorAttribs resb 1
.FrameBuffer resd 1
.Reserved1 resd 1
.Reserved2 resw 1
.ReservedSpace resb 213
endstruc
;; Initialization
VesaModeInfo:
istruc VbeModeStruct
at VbeModeStruct.Attributes, dw 0
at VbeModeStruct.WindowAttribsA, db 0
at VbeModeStruct.WindowAttribsB, db 0
at VbeModeStruct.WindowGranKb, dw 0
at VbeModeStruct.WindowSizeKb, dw 0
at VbeModeStruct.WindowASegment, dw 0
at VbeModeStruct.WindowBSegment, dw 0
at VbeModeStruct.FuncPtrPosition, dd 0
at VbeModeStruct.BytesPerScanline, dw 0
at VbeModeStruct.ResolutionX, dw 0
at VbeModeStruct.ResolutionY, dw 0
at VbeModeStruct.CharCellWidth, db 0
at VbeModeStruct.CharCellHeight, db 0
at VbeModeStruct.NumPlanes, db 0
at VbeModeStruct.Bpp, db 0
at VbeModeStruct.NumBanks, db 0
at VbeModeStruct.MemoryModel, db 0
at VbeModeStruct.BankSizeKb, db 0
at VbeModeStruct.MaxImagePages, db 0
at VbeModeStruct.Reserved, db 0
at VbeModeStruct.RedMaskSize, db 0
at VbeModeStruct.RedFieldPos, db 0
at VbeModeStruct.GreenMaskSize, db 0
at VbeModeStruct.GreenFieldPos, db 0
at VbeModeStruct.BlueMaskSize, db 0
at VbeModeStruct.BlueFieldPos, db 0
at VbeModeStruct.AlphaMaskSize, db 0
at VbeModeStruct.AlphaFieldPos, db 0
at VbeModeStruct.DirectColorAttribs,db 0
at VbeModeStruct.FrameBuffer, dd 0
at VbeModeStruct.Reserved1, dd 0
at VbeModeStruct.Reserved2, dw 0
at VbeModeStruct.ReservedSpace, times 213 db 0
iend
; Etc
wOptimizedVesaMode dw 0
wCurrentResX dw 0
wCurrentResY dw 0 ; Now parse list
xor eax, eax
mov es, ax
mov esi, dword [VesaControllerInfo + VbeControllerStruct.ModeListPtr]
call VesaFindBestSuitableMode
; **************************
; VesaFindBestSuitableMode
; IN:
; - ES:SI: List of Modes
; **************************
VesaFindBestSuitableMode:
; Save state
pushad
.modeListLoop:
; Null the buffer
push esi
xor eax, eax
mov edi, VesaModeInfo ; Structure to read mode information
mov ecx, 63 ; size of structure
rep stosd
pop esi
; Load mode
mov cx, word [es:si] ; Read first 16-bit from the
; ModeListPtr of 0x4F00 function.
; It should have a video mode id
; End of list?
cmp cx, 0xFFFF ; Check if it is end of the list.
je .Done
; Get Video mode info by its id
mov ax, 0x4F01
mov edi, VesaModeInfo
int 0x10
; Did it work?
test ah, ah
jne .NextEntry
cmp al, 0x4F
jne .NextEntry
; Now lets parse
mov ax, word [VesaModeInfo + VbeModeStruct.Attributes]
; We want Color, Graphics, LFB
and ax, 0x009B
cmp ax, 0x009B
jne .NextEntry
; We want 32 bit modes!! ALPHA FTW
mov al, byte [VesaModeInfo + VbeModeStruct.Bpp]
cmp al, 0x20
jne .NextEntry
; Ok... The modes we are looking for are:
; 1920x1080
; 1600x900
; 1280x720
; 1024x768
mov ax, word [VesaModeInfo + VbeModeStruct.ResolutionX]
mov bx, word [VesaModeInfo + VbeModeStruct.ResolutionY]
; Check 1024x768
cmp ax, 0x0400
jne .Check1280
cmp bx, 0x0300
jne .Check1280
jmp .ValidateEntry
; Ok, so this is 1024x768
.Check1280:
cmp ax, 0x0500
jne .Check1600
cmp bx, 0x02D0
jne .Check1600
jmp .ValidateEntry
.Check1600:
cmp ax, 0x0640
jne .Check1920
cmp bx, 0x0384
jne .Check1920
jmp .ValidateEntry
.Check1920:
cmp ax, 0x0780
jne .NextEntry
cmp bx, 0x0438
jne .NextEntry
.ValidateEntry:
; Check if we have better stored
cmp ax, word [wCurrentResX]
jbe .NextEntry
cmp bx, word [wCurrentResY]
jbe .NextEntry
; Save
mov word [wCurrentResX], ax
mov word [wCurrentResY], bx
mov word [wOptimizedVesaMode], cx
.NextEntry:
; Increase esi
add esi, 2
jmp .modeListLoop
.Done:
; Return
popad
retLeave a comment
Your email address will not be published. Required fields are marked *
