Skip to main content
The terminal driver provides a text-mode interface built on top of the framebuffer driver. It renders characters using PSF (PC Screen Font) fonts and supports a subset of ANSI escape sequences for colored output.

Overview

The terminal operates in character-based coordinates while rendering to a pixel-based framebuffer. It features:
  • PSF2 font rendering
  • 16-color ANSI color palette
  • Automatic scrolling
  • Cursor tracking
  • Escape sequence parsing

Architecture

The terminal sits between kernel logging functions and the framebuffer:

Data Structures

PSF Font Format

The terminal uses PSF2 fonts defined by the psfont_t structure:
typedef struct {
    uint32_t magic;       // Magic bytes to identify PSF
    uint32_t version;     // Zero for PSF2
    uint32_t headersize;  // Offset of bitmaps in file (32)
    uint32_t flags;       // 0 if there's no unicode table
    uint32_t numglyph;    // Number of glyphs
    uint32_t glyph_size;  // Size of each glyph in bytes
    uint32_t height;      // Height in pixels
    uint32_t width;       // Width in pixels
    uint8_t data[];       // The actual font data
} psfont_t;

ANSI Color Palette

The terminal supports 16 standard ANSI colors:

Standard Colors (30-37, 40-47)

TERM_COLOR_BLACK     0x000000
TERM_COLOR_RED       0xaa0000
TERM_COLOR_GREEN     0x00aa00
TERM_COLOR_YELLOW    0xaaaa00
TERM_COLOR_BLUE      0x0000aa
TERM_COLOR_MAGENTA   0xaa00aa
TERM_COLOR_CYAN      0x00aaaa
TERM_COLOR_WHITE     0xaaaaaa

Bright/Light Colors

TERM_COLOR_LTBLACK   0x555555
TERM_COLOR_LTRED     0xff5555
TERM_COLOR_LTGREEN   0x55ff55
TERM_COLOR_LTYELLOW  0xffff55
TERM_COLOR_LTBLUE    0x5555ff
TERM_COLOR_LTMAGENTA 0xff55ff
TERM_COLOR_LTCYAN    0x55ffff
TERM_COLOR_LTWHITE   0xffffff

Default Colors

DEFAULT_FGCOLOR      TERM_COLOR_WHITE
DEFAULT_BGCOLOR      TERM_COLOR_BLACK

API Functions

term_init

Initializes the terminal driver.
void term_init();
Implementation from term.c:174-183:
void term_init()
{
    fb = fb_getinfo();

    term_width = fb->width / term_font.width;
    term_height = fb->height / term_font.height;

    term_clear();
    term_flush();
}
Calculates terminal dimensions in characters and clears the screen.

term_putchar

Outputs a single character to the terminal.
void term_putchar(uint8_t c);
Implementation from term.c:140-171:
void term_putchar(uint8_t c)
{
    if (parse_cmd_byte(c))
        return;

    switch (c) {
    case '\0':
        return;

    case '\n':
        cursor_x = 0;
        cursor_y++;
        break;

    case '\t':
        cursor_x += (cursor_x % 4 == 0) ? 0 : (4 - cursor_x % 4);
        break;

    default:
        putchar_at(c, cursor_x, cursor_y);
        cursor_x++;
    }

    if (cursor_x >= term_width) {
        cursor_x = 0;
        cursor_y++;
    }
    if (cursor_y >= term_height) {
        scroll();
        cursor_y = term_height - 1;
    }
}
Handles special characters and triggers scrolling when necessary.

term_clear

Clears the terminal screen with the background color.
void term_clear();
Implementation from term.c:130-138:
void term_clear()
{
    for (size_t y = 0; y < fb->height; y++)
        for (size_t x = 0; x < fb->width; x++)
            fb_putpixel(x, y, bgcolor);

    cursor_x = 0;
    cursor_y = 0;
}

term_flush

Flushes the terminal buffer to the display.
void term_flush();
Implementation from term.c:124-127:
void term_flush()
{
    fb_swap_buffers();
}
This calls the framebuffer’s buffer swap function to make changes visible.

term_setfgcolor / term_setbgcolor

Sets the foreground or background color.
void term_setfgcolor(uint32_t color);
void term_setbgcolor(uint32_t color);
Implementation from term.c:185-193:
void term_setfgcolor(uint32_t color)
{
    fgcolor = color;
}

void term_setbgcolor(uint32_t color)
{
    bgcolor = color;
}

term_getwidth / term_getheight

Returns terminal dimensions in characters.
uint32_t term_getwidth();
uint32_t term_getheight();
Implementation from term.c:195-203:
uint32_t term_getwidth()
{
    return term_width;
}

uint32_t term_getheight()
{
    return term_height;
}

ANSI Escape Sequences

The terminal implements a state machine parser for ANSI escape sequences:

Supported Sequences

ESC c
Clears the terminal screen.

Parser Implementation

The escape sequence parser from term.c:26-92 uses a state machine:
static bool parse_cmd_byte(uint8_t byte)
{
    static enum {
        READY,
        CMD_WAIT,
        PARAM_WAIT
    } state;
    static int cparams[10] = { 0 };
    static int cparamcount = 0;

    // State machine implementation...
}
States:
  • READY - Waiting for ESC (0x1B)
  • CMD_WAIT - Waiting for command character
  • PARAM_WAIT - Parsing numeric parameters

Font Rendering

Characters are rendered pixel-by-pixel from the PSF font data: Implementation from term.c:107-121:
static void putchar_at(uint8_t c, size_t px, size_t py)
{
    uint8_t* glyph = &term_font.data[c * term_font.glyph_size];
    size_t x = px * term_font.width, y = py * term_font.height;

    static const uint8_t masks[8] = { 128, 64, 32, 16, 8, 4, 2, 1 };

    for (size_t i = 0; i < term_font.height; i++) {
        for (size_t j = 0; j < term_font.width; j++) {
            fb_putpixel(x + j, y + i, (glyph[i] & masks[j]) ? fgcolor : bgcolor);
        }
    }
}
Each glyph is a bitmap where set bits represent foreground pixels.

Scrolling

When the cursor reaches the bottom of the screen, the terminal scrolls: Implementation from term.c:95-104:
static void scroll()
{
    for (size_t y = 0; y < fb->height - term_font.height; y++)
        for (size_t x = 0; x < fb->width; x++)
            fb_putpixel(x, y, fb_getpixel(x, y + term_font.height));

    for (size_t y = fb->height - term_font.height; y < fb->height; y++)
        for (size_t x = 0; x < fb->width; x++)
            fb_putpixel(x, y, bgcolor);
}
The screen content is shifted up by one character line, and the bottom line is cleared.
Scrolling operates at the pixel level, not character level. This allows partial scrolling effects but is computationally more expensive.

Special Character Handling

CharacterBehavior
\0 (NUL)Ignored
\n (LF)Move to start of next line
\t (TAB)Advance to next 4-character boundary
ESC sequencesColor control and clear screen
Tab implementation from term.c:154-155:
case '\t':
    cursor_x += (cursor_x % 4 == 0) ? 0 : (4 - cursor_x % 4);

Source Files

kernel/dev/term/term.h

Build docs developers (and LLMs) love