VGA¶
Register Groups¶
VGA hardware is controlled through five groups of I/O-mapped registers. All access is through the kernel's outb/inb wrappers.
| Group | Index Port | Data Port | Purpose |
|---|---|---|---|
| Sequencer (SEQ) | 0x3C4 |
0x3C5 |
Memory sequencing, clock, plane write masks |
| CRTC | 0x3D4 |
0x3D5 |
Display timing, scan line counts, cursor position |
| Graphics Controller (GC) | 0x3CE |
0x3CF |
Read/write modes, color compare, bit masks |
| Attribute Controller (AC) | 0x3C0 |
0x3C0 |
Palette, display enable, pixel clock |
| Miscellaneous Output | 0x3C2 |
— | Clock select, sync polarity, I/O address select |
The Attribute Controller uses a single port for both index and data, toggled by an internal flip-flop. It must be reset by reading 0x3DA (Input Status 1) before writing.
Supported Hardware Modes¶
set_video_mode(mode: u8) -> bool in video/vga_hw.rs programs all five register groups for the requested mode. Returns true on success, false for an unknown mode number.
| Mode | Number | Resolution | Colors | Use |
|---|---|---|---|---|
| Text 80×25 | 0x03 |
720×400 (character) | 16 | Kernel console, default |
| 16-color 320×200 | 0x0D |
320×200 | 16 | Legacy planar graphics |
| 16-color 640×480 | 0x12 |
640×480 | 16 | Higher-res planar graphics |
| 256-color 320×200 | 0x13 |
320×200 | 256 | Mode 13h, linear byte-per-pixel |
Mode-Switch Sequence¶
For all modes:
- Write Miscellaneous Output register (
0x3C2). - Write Sequencer registers (
0x3C4/0x3C5), index 0–4. - Unlock CRTC (clear protect bit on index
0x11), then write CRTC registers. - Write Graphics Controller registers.
- Reset AC flip-flop (read
0x3DA), then write all 21 Attribute Controller registers (indices 0–20), finishing with a write of0x20to0x3C0to re-enable display output. - For mode
0x03only: callclear_text_buf(),restore_font(),restore_text_dac().
Mode 0x03 — Text Mode Restoration¶
Switching back to text mode from a graphics mode requires three additional steps that reprogram state the BIOS would normally set up.
clear_text_buf()¶
Fills the VGA text buffer at 0xB8000 with space characters (byte 0x20) and attribute byte 0x07 (light gray on black). Clears all 80×25 = 2000 character cells.
restore_font()¶
Reloads the embedded 8×16 font (VGA_FONT_8X16, 4096 bytes) into VGA plane 2 (the font plane). The sequence:
SEQ[0x00] ← 0x01 (synchronous reset)
SEQ[0x02] ← 0x04 (write to plane 2 only)
SEQ[0x04] ← 0x07 (sequential addressing, odd/even disabled)
GC[0x04] ← 0x02 (read plane 2)
GC[0x05] ← 0x00 (write mode 0, read mode 0)
GC[0x06] ← 0x00 (A000-BFFF range, graph mode off)
for each glyph g (0..256):
write 16 bytes of VGA_FONT_8X16[g*16..] to 0xA0000 + g*32
SEQ[0x02] ← 0x03 (restore write to planes 0+1)
SEQ[0x04] ← 0x03 (odd/even addressing)
GC[0x04] ← 0x00 (read plane 0)
GC[0x05] ← 0x10 (odd/even read)
GC[0x06] ← 0x0E (B800-BFFF range, text mode)
SEQ[0x00] ← 0x03 (release reset)
Each glyph occupies 32 bytes in plane 2 (only the first 16 are significant; the upper 16 are zero-padding required by VGA).
restore_text_dac()¶
Programs the VGA DAC (Digital-to-Analog Converter) with the standard 16-color EGA-compatible palette. The DAC is accessed via:
- Write palette index to
0x3C8 - Write R, G, B (6-bit, 0–63 each) sequentially to
0x3C9
The standard palette maps the 16 EGA attribute colors (0–15) to their canonical RGB values (e.g., index 0 = black 0,0,0; index 7 = light gray 42,42,42; index 15 = white 63,63,63).
Text Mode Writer (video/vga.rs)¶
The Writer struct manages the kernel's VGA text console.
For an EFI text session (console=fb), the same writer uses a RAM character
buffer and video/console.rs draws 8x16 glyphs, foreground/background colors,
scrolling, and an underline cursor on the boot framebuffer. Glyphs scale by
an integer factor up to 4 to fit the display. The grid stays
80x25; stride and RGB field positions come from Multiboot2. Supported formats
are 24-bit and 32-bit RGB below 4 GiB, at least 640x400. VGA cursor ports are
not accessed by this output path. The kernel shell runs, Memento does not
autostart, and the clock that writes directly into VGA memory is omitted.
pub struct Writer {
col_pos: usize,
row_pos: usize,
color_code: ColorCode,
buffer: *mut Buffer, // 0xB8000
}
Constants¶
| Constant | Value |
|---|---|
BUFFER_WIDTH |
80 |
BUFFER_HEIGHT |
25 |
BUFFER_ADDRESS |
0xB8000 |
Colors¶
Color is a 4-bit VGA attribute value (0–15). ColorCode packs foreground and background:
ColorCode = (background << 4) | foreground
Standard color indices: Black=0, Blue=1, Green=2, Cyan=3, Red=4, Magenta=5, Brown=6, LightGray=7, DarkGray=8, LightBlue=9, LightGreen=10, LightCyan=11, LightRed=12, Pink=13, Yellow=14, White=15.
write_byte(byte: u8)¶
| Byte | Action |
|---|---|
\n (0x0A) |
Advance to next row (new_line()) |
\r / 0x08 |
Backspace: decrement col_pos, write space, do not advance |
| Other | Write character cell at (col_pos, row_pos), advance col_pos; call new_line() on column overflow |
new_line()¶
When row_pos reaches BUFFER_HEIGHT - 1, the entire buffer is scrolled up one row: rows 1–24 are copied to rows 0–23 using direct memory writes to 0xB8000. Row 24 is cleared. When row_pos < BUFFER_HEIGHT - 1, row_pos is incremented and col_pos is reset to 0.
Hardware Cursor (move_cursor())¶
The hardware text cursor is positioned by writing the linear cell index (row * 80 + col) as two bytes to CRTC:
CRTC[0x0E] ← (position >> 8) & 0xFF (high byte)
CRTC[0x0F] ← position & 0xFF (low byte)
Called after every character write that changes the cursor position.
VGA VRAM Window¶
The VGA VRAM window (0xA00_000 virtual, 0xA0000 physical, 64 KiB) is mapped on demand by syscall 0x14 (map_vram). The mapping uses fine-grained 4 KiB pages (a P1 table allocated from PAGE_TABLE_POOL) rather than the 2 MiB huge pages used elsewhere.
The P1 table is allocated once per process on the first map_vram call. Repeated calls are idempotent — the same P1 is reused. After mapping, userland can write directly to 0xA00_000 as Mode 13h VRAM (320×200, one byte per pixel, 64000 bytes).
The kernel's TLB is flushed by reloading CR3 after mapping.
Legacy VGA Module (src/vga/)¶
An older VGA module lives under src/vga/ (distinct from src/video/). It contains:
src/vga/buffer.rs— character/color cell typessrc/vga/write.rs— writer implementationsrc/vga/screen.rs— screen helper
This module predates the current video/ subsystem. The canonical implementation is src/video/vga.rs.
Related documentation: Video Overview, Kernel Internals, Video and Audio ABI.