VGA Text Console Backend

tomOSii uses the legacy VGA text output capabilities just for simplicity. This requires using BIOS boot, but immediately enables text output by writing characters to the video buffer. Booting using EFI would require implementing a framebuffer console and bitmap fonts. We hope to provide such an interface so that later a framebuffer console can be added.

The VGA text console backend is implemented in os/drivers/console/text_console_backend.c.

This is a “legacy” text console backend providing very simple means for putting ascii characters onto the screen, i.e., into the VGA text memory starting at 0xB8000. This driver handles only the interaction/communication with the hardware. A higher-level console abstraction is implemented separately, e.g., in basic_console.c.

Note

The port i/o implementation can be found in text_console_backend_port_io.c. That functionality is kept separately in order to facilitate testing.

Initialization

This driver is initialized by calling

void text_console_backend_init(void)

Initialize and register the text console backend module.

Register the console backend operations as the default backend operations to the console subsystem. That way, new consoles will use those operations.

The remaining initialization is deferred until the backend is being opened, i.e., until __text_con_be_open is being called.

^ Back to top.

Console Backend Operations

This backend implements the console backend operations:

Open

Implements

void (*con_be_open)(console_t *con)

Open the backend, initialize the required fields in con.

of struct console_backend_operations_t (documentation):

static void __text_con_be_open(console_t *con)

Open the backend, initialize the required fields in con.

When opening this backend, the video buffer is cleared to contain the character \0 with attribute 0x08, i.e., gray on black. The cursor will be enabled, with width 1 and position 0, i.e., the first position in the video buffer. The size is hardcoded to 80x25.

Both, size and default attribute are stored in the passed console data structure, so that the console can use these values.

^ Back to top.

Put Character

Implements

void (*con_be_putc)(console_t *con, uint16_t ca, unsigned int y, unsigned int x)

Emit one character with attributes ca to [x, y].

of struct console_backend_operations_t (documentation):

static void __text_con_be_putc(console_t *con, uint16_t ca, unsigned int y, unsigned int x)

Emit one character with attributes ca to [x, y].

x and y are checked to be in the bounds stored in con. If those are out of bounds, the function does nothing and returns. Otherwise, the character and attribute combo ca is put into the video memory location denoted by [x, y].

Parameters:
  • con – : console data, e.g., width, height, …

  • ca – : character and its attribute, e.g., colour

  • y – : row to put the character into

  • x – : column to put the character into

^ Back to top.

Clear Range

Implements

void (*con_be_clear)(console_t *con, unsigned int y, unsigned int x, size_t count)

Erase count characters starting at [x, y].

of struct console_backend_operations_t (documentation):

static void __text_con_be_clear(console_t *con, unsigned int y, unsigned int x, size_t count)

Erase count characters starting at [x, y].

x and y are checked to be in the bounds stored in con. If those are out of bounds, the function does nothing and returns. Otherwise, count consecutive elements on the text display are erased starting at [x, y]. For those elements, the video buffer is set to contain the character \0 with attribute 0x08, i.e., gray on black.

Note

The first and the last line of the region to be erased do not necessarily need to be full lines.

Warning

[x, y] + count is not checked for being out of bounds!

Parameters:
  • con – : console data, e.g., width, height, …

  • y – : row to start clearing from

  • x – : column to start erasing from

  • count – : number of consecutive elements to erase

^ Back to top.

Cursor

Implements

void (*con_be_cursor)(console_t *con, unsigned int y, unsigned int x, bool enable)

Set the cursor’s [x, y] position and enabled state.

of struct console_backend_operations_t (documentation):

static void __text_con_be_cursor(console_t *con, unsigned int y, unsigned int x, bool enabled)

Set the cursor’s [x, y] position and enabled state.

x and y are checked to be in the bounds stored in con. If those are out of bounds, the function does nothing and returns. Otherwise, the cursor is moved to position [x, y]. Furthermore, the cursor is enabled or disabled, depending on the value of the parameter enabled.

Parameters:
  • con – : console data, e.g., width, height, …

  • y – : row to set the cursor to

  • x – : column to set the cursor to

  • enabled – : cursor state (true: visible)

^ Back to top.

Scroll

Implements

void (*con_be_scroll)(console_t *con, unsigned int top, unsigned int bottom, con_scroll_t dir, unsigned int lines)

scroll the console from top (inclusive) to bottom (exclusive) in direction dir by lines.

of struct console_backend_operations_t (documentation):

static void __text_con_be_scroll(console_t *con, unsigned int top, unsigned int bottom, con_scroll_t dir, unsigned int lines)

Scroll the console.

top and bottom are checked to be in the bounds stored in con. If those are out of bounds, the function does nothing and returns. Otherwise, define a region of the output to be scrolled starting at line top (inclusive) ending at line bottom (exclusive). The content of this region is scrolled upwards, independent of dir, by lines number of lines.

The sub-region that is “freed” by the scrolling, is cleared to the default attribute, as a Clear would do (see __text_con_be_clear).

Will panic, if

  • dir is CON_SCROLL_DOWN.

  • dir is invalid.

Todo:

Implement scrolling both ways.

Note

Currently just scrolls upwards.

Parameters:
  • top – : First line of scrolling region.

  • bottom – : Last line of scrolling region.

  • dir – : Direction for scrolling.

  • lines – : Number of lines to scroll the text into directiondir.

^ Back to top.

Port-I/O Implementation

Port-I/O for the VGA text console backend is implemented in os/drivers/console/text_console_backend_port_io.c.

This is the port i/o part of the implementation of the backend in text_console_backend.c.

This functionality is kept in a separate source file in order to facilitate testing the console backend without having to mock the individual port i/o calls. That way, the complete helper functions can be replaced by stubs instead.

Note

The provided functions are considered internal to the text console backend. They are not intended to be called somewhere else.

Functions

void __text_con_be_cursor_thickness(uint8_t thickness)

Set the cursor’s thickness.

The cursor’s thickness is set by setting the start and end lines of the cursor. The cursor will always end on the bottom scanline. In order to set the start/end, the respective register needs to be first retrieved from the hardware. Since it might contain more info, data needs to be masked and then or’d with the new start/end scanline.

Note

Setting the thickness also enables the cursor. In order to preserve the enabled state, the data retrieved from the cursor start register needs to be masked with CURSOR_START_ENABLE_PRESERVE_BITS instead of CURSOR_START_PRESERVE_BITS.

void __text_con_be_cursor_enabled(bool enabled)

Set the cursor’s enabled state, i.e., show/hide the cursor.

The cursor’s enabled state is stored in bit 5 of the cursor start register. In order to set the enabled state, the respective register needs to be first retrieved from the hardware. Bit 5 is then set according to the passed parameter enabled.

void __text_con_be_cursor_position(uint16_t position)

Set the cursor’s position (y * WIDTH + x).

The cursor’s position is provided as a 16-bit offset into the video memory. The high- and the low-byte are transferred separately.

Enums

port i/o ports, registers and bitmasks for vga text mode

Values:

enumerator CURSOR_COMMAND

command port for cursor control

enumerator CURSOR_DATA

data port for cursor control

enumerator CURSOR_START

cursor start register

enumerator CURSOR_END

cursor end register

enumerator CURSOR_POS_HIGH

cursor position high register

enumerator CURSOR_POS_LOW

cursor position low register

enumerator CURSOR_START_PRESERVE_BITS

bitmask for cursor start

enumerator CURSOR_START_ENABLE_PRESERVE_BITS

bitmask for cursor start, preserve enable state

enumerator CURSOR_END_PRESERVE_BITS

bitmask for cursor end

enumerator CURSOR_DISABLE_BIT

bitmask for cursor enabled

enumerator CURSOR_BOTTOM_SCANLINE

bottom scanline for cursor