Framebuffer Device (/dev/fb0) Architecture
In BoredOS, graphical output is managed via a standard, Linux-compatible framebuffer device node registered at /dev/fb0. This node provides a raw interface for userland applications to access and manipulate physical screen pixels directly.
1. VFS Registration and Routing
The virtual file system (VFS) in src/fs/vfs.c manages all files under the /dev hierarchy. When an application opens /dev/fb0, the kernel assigns it a special device type:
#define DEVICE_TYPE_FRAMEBUFFER 2
Once opened, standard file descriptor operations (read, write, lseek, ioctl, mmap) on this descriptor are intercepted by the VFS and routed to dedicated framebuffer device operations rather than standard disk/filesystem operations.
2. Direct Physical Screen Operations
Unlike a standard file, /dev/fb0 maps directly to the active physical screen memory allocated during the boot phase (configured by Limine).
At boot, the kernel queries the physical screen configuration using:
graphics_fb_params_t params = graphics_get_fb_params();
This returns the physical hardware framebuffer parameters:
address: The physical start address of display memory (e.g.0xfd000000).width: Display width in pixels (e.g.1024).height: Display height in pixels (e.g.768).bpp: Bits per pixel (always32for BoredOS, packing BGRA).pitch: The actual physical line length in bytes (width * 4 + alignment padding).
Write and Seek Operations
When a userland application writes to /dev/fb0:
- The kernel maintains a seek offset
posinside the VFS file descriptor structure. - The userland writes a byte array of pixel data.
- The VFS checks that the write is within the bounds of screen memory (
width * height * 4bytes). - The kernel performs a direct
memcpyfrom the user's buffer to the physical address offset:memcpy((void*)(g_fb->address + pos), user_buf, size); - The descriptor offset
posis advanced by the number of bytes successfully written. - The
lseek()system call is fully supported, allowing applications to reset the pixel cursor back to0(start of screen) or seek to a precise pixel offset before writing.
3. Supported Linux-Compatible Ioctls
To support standard porting of unix graphic utilities (such as terminal emulators and future display servers), /dev/fb0 implements standard Linux ioctl commands. These structures are defined in external/libc/include/sys/ioctl.h:
FBIOGET_VSCREENINFO (0x4600)
Returns variable screen information using the fb_var_screeninfo_t struct:
| Field | Value | Meaning |
|---|---|---|
xres / yres |
e.g. 1024 / 768 |
Active visible resolution |
xres_virtual / yres_virtual |
e.g. 1024 / 768 |
Virtual resolution |
bits_per_pixel |
32 |
Color depth (4 bytes per pixel) |
red / green / blue |
8-bit sizes, specific offsets | Tells userland the exact bit configuration of colors (BGRA layout) |
FBIOGET_FSCREENINFO (0x4602)
Returns fixed hardware parameters using the fb_fix_screeninfo_t struct:
| Field | Value | Meaning |
|---|---|---|
smem_start |
e.g. 0xfd000000 |
Physical start address of display memory |
smem_len |
line_length * yres |
Total size of display memory |
visual |
FB_VISUAL_TRUECOLOR (2) |
Layout type (TrueColor packed BGRA) |
line_length |
e.g. 4096 |
Pitch of a single line in bytes |
4. Zero-Copy Performance via mmap
BoredOS supports memory mapping for high-performance, zero-copy graphics rendering.
When a process invokes the sys_mmap system call on /dev/fb0's file descriptor:
- The kernel validates that the offset is valid and that the requested size fits within the physical framebuffer limits (
smem_len). - The virtual memory manager (VMM) maps the physical address range (
g_fb->address) directly into the process's page table at an allocated user virtual address. - This mapping is created with Read/Write permissions and caching policies suitable for graphics memory (Write-Combining).
- The userland process receives a direct pointer to screen memory:
uint32_t *pixels = (uint32_t *)mmap(NULL, screen_size, PROT_READ|PROT_WRITE, MAP_SHARED, fb_fd, 0); - Writes to this pointer immediately modify pixels on the physical screen without any system call context-switch overhead, achieving maximum possible rendering performance.
5. Console Coexistence and Mode Toggling
Since the kernel contains an active text console blitting loop, direct writes to /dev/fb0 would normally be clobbered by terminal text characters whenever a background tick fires.
To prevent this, userland applications must open their active controlling TTY console (/dev/tty0 or standard input descriptor 0) and execute:
ioctl(0, KDSETMODE, (void*)KD_GRAPHICS);
This sets the TTY blit toggle to false, pausing the background console text rendering. The application has exclusive, uninterrupted control of the display.
Before exiting, the application MUST restore text mode to resume normal terminal behavior:
ioctl(0, KDSETMODE, (void*)KD_TEXT);