|
miniOS
x86_64 hobby kernel with SMP, VFS, and POSIX process model
|
miniOS includes a layered terminal stack: a VT/ANSI parser with two rendering backends (VGA text mode and GOP linear framebuffer), a POSIX-like line discipline, and a VFS character device node at /dev/tty.
When the kernel is compiled with -DCONSOLE_GOP (default) and GRUB provides a Multiboot2 framebuffer tag, gop_init_from_mb2() in main.c maps the physical framebuffer and calls vt_init_gop(). All subsequent output goes through the pixel backend. Without a Multiboot2 framebuffer the VGA text-mode backend is used as a fallback.
vt_init() initialises the ANSI escape parser and the active renderer. All output passes through vt_write_byte(c) or vt_write(buf, len).
The VT core contains a full UTF-8 state machine in vt_handle_normal_char(). Multi-byte sequences (2, 3, or 4 bytes) are accumulated and decoded to a Unicode codepoint. On an invalid continuation byte the partial sequence is flushed as individual Latin-1 bytes before retrying.
In GOP mode the codepoint is looked up in gop_cp_map[] (a sorted 557-entry table, binary-searchable) derived from the LatArCyrHeb-16 PSF2 font. In VGA mode codepoints in the range U+0080–U+00FF are mapped to their nearest CP437 equivalent via a lookup table.
The keyboard driver emits Latin-1 characters (e.g. ä, ö, ü, ß) as 2-byte UTF-8 before calling tty_keyboard_input(). Backspace in canonical mode strips the entire UTF-8 character (all trailing continuation bytes plus the lead byte).
GOP mode uses the LatArCyrHeb-16 PSF2 font (8×16 pixels, 512 glyphs). The font header is auto-generated by scripts/gen_font.py from the system font at /usr/share/kbd/consolefonts/LatArCyrHeb-16.psfu.gz and written to include/miniOS/drivers/gop_font.h. Run make to regenerate if the font source changes.
Key codepoints: ASCII U+0020–U+007E identity-mapped to glyphs 32–126; Latin-1 (ä=U+00E4, ö=U+00F6, ü=U+00FC) present; em dash (—=U+2014) at glyph 489.
A 2-scanline underline cursor is drawn over the current cell in the GOP framebuffer. It blinks at 5 Hz (100 ms on / 100 ms off):
In VGA mode the hardware cursor is driven via VGA CRT registers (no blink logic in software).
A static 160×50 array of uint16_t gop_cell_glyph[][] and uint8_t gop_cell_attr[][] mirrors every cell on screen. All write, clear, and scroll operations update both the pixel framebuffer and the backing store atomically under vt_fb_lock. This is required so gop_erase_cursor() can restore cell contents correctly.
vt_fb_lock (a spinlock_t initialised with SPINLOCK_INIT) protects all framebuffer and backing-store writes. It is acquired with spinlock_irqsave so that the LAPIC timer ISR (which calls vt_cursor_tick()) cannot race with kernel writers on the same or another CPU.
| Sequence | Effect |
|---|---|
| ESC[H | Move cursor to (1,1) |
| ESC[r;cH | Move cursor to row r, column c |
| ESC[A/B/C/D | Cursor up / down / right / left |
| ESC[2J | Erase entire screen |
| ESC[K | Erase to end of line |
| ESC[m | Reset SGR attributes (foreground + background) |
| ESC[Nm | Set foreground color N (30-37, 90-97) |
| ESC[N;5;Mm | 256-color foreground (mapped to nearest VGA 16-color) |
| ESC[?25h/l | Show / hide cursor |
256-color SGR requests (38;5;N) map to the nearest 16-color palette entry using squared Euclidean distance in RGB space. In GOP mode the 16-color palette is precomputed as 32bpp pixel values (respecting the framebuffer's red/green/blue bit positions) by vt_init_gop(). In VGA mode the mapping produces a 4-bit VGA attribute.
vt_get_winsize() returns the active grid dimensions: 160×50 in GOP mode (1280×800 / 8×16 font), 80×25 in VGA text mode. TIOCGWINSZ returns these values.
The line discipline is the policy layer that decides how input characters from the keyboard are buffered and delivered to userspace read() calls.
When ECHO is set in c_lflag, each input character from tty_keyboard_input() is forwarded to vt_write_byte() so it appears on screen.
The kernel termios structure uses Linux-compatible field layout:
Supported ioctls:
| Command | Value | Action |
|---|---|---|
| TCGETS | 0x5401 | Copy kernel termios to user pointer |
| TCSETS | 0x5402 | Copy user termios to kernel state |
| TCSETSW | 0x5403 | Same as TCSETS (drain not implemented) |
| TIOCGWINSZ | 0x5413 | Copy {ws_row, ws_col} to user pointer (dynamic; 160×50 GOP, 80×25 VGA) |
| TIOCSCTTY | 0x540E | Accept (no-op in single-TTY kernel) |
| TIOCNOTTY | 0x5422 | Accept (no-op) |
The shell performs the following at startup: