working on exposing vga to userspace

This commit is contained in:
2026-07-16 14:44:08 -05:00
parent 37aa46c847
commit b588634253
16 changed files with 251 additions and 139 deletions

View File

@@ -48,6 +48,9 @@ static uint32_t cpio_read(struct vfs_node* node, uint32_t offset, uint32_t size,
} }
static vfs_node_t* cpio_find_or_create(vfs_node_t* root_node, const char* path) { static vfs_node_t* cpio_find_or_create(vfs_node_t* root_node, const char* path) {
if (strcmp(path, "fonts") == 0) {
kprintf("found fonts folder\n");
}
vfs_node_t* current = root_node; vfs_node_t* current = root_node;
char path_cpy[256]; char path_cpy[256];

View File

@@ -9,6 +9,7 @@ int is_transmit_empty() {
void write_serial(char a) { void write_serial(char a) {
while (is_transmit_empty() == 0); while (is_transmit_empty() == 0);
if (a == '\n') outb(COM1, '\r');
outb(COM1, a); outb(COM1, a);
} }

View File

@@ -1,3 +1,4 @@
#include "vfs.h"
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
@@ -9,6 +10,8 @@
#include <common.h> #include <common.h>
#include <memory/mm.h> #include <memory/mm.h>
#include <user/video.h>
static uint32_t framebuffer_address; static uint32_t framebuffer_address;
static uint32_t framebuffer_width; static uint32_t framebuffer_width;
static uint32_t framebuffer_height; static uint32_t framebuffer_height;
@@ -34,36 +37,45 @@ vga_color_t VGA_COLOR_RED = {0, 0, 255, 255};
vga_color_t VGA_COLOR_GREEN = {0, 255, 0, 255}; vga_color_t VGA_COLOR_GREEN = {0, 255, 0, 255};
vga_color_t VGA_COLOR_BLUE = {255, 0, 0, 255}; vga_color_t VGA_COLOR_BLUE = {255, 0, 0, 255};
uint32_t vga_mmap(vfs_node_t* node, uint32_t address) {
uint32_t fb_size_bytes = framebuffer_height * framebuffer_pitch;
uint32_t num_pages = (fb_size_bytes + 4095) / 4096;
for (uint32_t i = 0; i < num_pages; i++) {
uint32_t phys_addr = framebuffer_address + (i * 4096);
uint32_t virt_addr = address + (i * 4096);
map_page(virt_addr, phys_addr, PAGE_PRESENT | PAGE_WRITABLE);
}
return address;
}
uint32_t vga_ioctl(vfs_node_t* node, uint32_t request, void* arg) {
if (request == FBIOGET_INFO) {
fb_info_t* info = (fb_info_t*)arg;
info->width = framebuffer_width;
info->height = framebuffer_height;
info->pitch = framebuffer_pitch;
info->fb_size = framebuffer_total_pixels;
info->bpp = framebuffer_bpp;
return 1;
}
return 0;
}
void vga_init( void vga_init(
vfs_node_t* dev,
uint32_t fb_paddr, uint32_t fb_paddr,
uint32_t fb_width, uint32_t fb_width,
uint32_t fb_height, uint32_t fb_height,
uint32_t fb_pitch, uint32_t fb_pitch,
uint8_t fb_bpp, uint8_t fb_bpp
uint8_t _red_mask_sz,
uint8_t _red_field_pos,
uint8_t _green_mask_sz,
uint8_t _green_field_pos,
uint8_t _blue_mask_sz,
uint8_t _blue_field_pos
) { ) {
framebuffer_address = VGA_FRAMEBUFFER; framebuffer_address = fb_paddr;
framebuffer_width = fb_width;
red_mask_sz = _red_mask_sz; framebuffer_height = fb_height;
red_field_pos = _red_field_pos; framebuffer_total_pixels = framebuffer_width * framebuffer_height;
green_mask_sz = _green_mask_sz; framebuffer_pitch = fb_pitch;
green_field_pos = _green_field_pos; framebuffer_bpp = fb_bpp;
blue_mask_sz = _blue_mask_sz;
blue_field_pos = _blue_field_pos;
print_serial("initializing vga.\r\n");
print_serial_hex(fb_paddr);
print_serial("\r\n");
print_serial_hex(framebuffer_address);
print_serial("\r\n");
print_serial("BPP: ");
print_serial_hex(fb_bpp);
print_serial("\r\n");
uint32_t fb_size_bytes = fb_height * fb_pitch; uint32_t fb_size_bytes = fb_height * fb_pitch;
uint32_t num_pages = (fb_size_bytes + 4095) / 4096; uint32_t num_pages = (fb_size_bytes + 4095) / 4096;
@@ -73,18 +85,15 @@ void vga_init(
map_page(virt_addr, phys_addr, PAGE_PRESENT | PAGE_WRITABLE); map_page(virt_addr, phys_addr, PAGE_PRESENT | PAGE_WRITABLE);
} }
framebuffer_width = fb_width;
framebuffer_height = fb_height;
framebuffer_total_pixels = framebuffer_width * framebuffer_height;
framebuffer_pitch = fb_pitch;
framebuffer_bpp = fb_bpp;
vga_clear_scrn(0x00000000); vga_clear_scrn(0x00000000);
dev->flags = VFS_CHARDEVICE;
dev->mmap = vga_mmap;
dev->ioctl = vga_ioctl;
} }
uint32_t vga_get_framebuffer() { uint32_t vga_get_framebuffer() {
return framebuffer_address; return VGA_FRAMEBUFFER;
} }
uint32_t vga_get_width() { uint32_t vga_get_width() {
@@ -124,25 +133,3 @@ void vga_clear_scrn(uint32_t color) {
} }
} }
} }
uint32_t vga_write(vfs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buf) {
return size;
}
void test_draw_vertical_line(uint32_t x, uint32_t y_start, uint32_t y_end, uint32_t color) {
if (framebuffer_address == 0) return;
uint8_t* fb_bytes = (uint8_t*)framebuffer_address;
for (uint32_t y = y_start; y < y_end; y++) {
if (y >= framebuffer_height) break;
uint8_t* row = fb_bytes + (y * framebuffer_pitch);
uint32_t* pixel_row = (uint32_t*)row;
if (x < framebuffer_width) {
pixel_row[x] = color;
}
}
}

View File

@@ -17,19 +17,15 @@ extern vga_color_t VGA_COLOR_BLACK;
extern vga_color_t VGA_COLOR_RED; extern vga_color_t VGA_COLOR_RED;
extern vga_color_t VGA_COLOR_GREEN; extern vga_color_t VGA_COLOR_GREEN;
extern vga_color_t VGA_COLOR_BLUE; extern vga_color_t VGA_COLOR_BLUE;
extern vga_color_t VGA_COLOR_ROCKOS;
void vga_init( void vga_init(
vfs_node_t* dev,
uint32_t fb_paddr, uint32_t fb_paddr,
uint32_t fb_width, uint32_t fb_width,
uint32_t fb_height, uint32_t fb_height,
uint32_t fb_pitch, uint32_t fb_pitch,
uint8_t fb_bpp, uint8_t fb_bpp
uint8_t red_mask_sz,
uint8_t red_field_pos,
uint8_t green_mask_sz,
uint8_t green_field_pos,
uint8_t blue_mask_sz,
uint8_t blue_field_pos
); );
uint32_t vga_get_framebuffer(); uint32_t vga_get_framebuffer();
@@ -42,6 +38,4 @@ void vga_clear_scrn(uint32_t color);
uint32_t vga_write(vfs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buf); uint32_t vga_write(vfs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buf);
void test_draw_vertical_line(uint32_t x, uint32_t y_start, uint32_t y_end, uint32_t color);
#endif #endif

View File

@@ -125,26 +125,9 @@ void kmain(multiboot_info* mbi) {
init_pmm((void*)mmap_virtual_addr, mbi->mmap_length); init_pmm((void*)mmap_virtual_addr, mbi->mmap_length);
init_page_tables(); init_page_tables();
vga_init(vga_fb_address, disable_interrupts();
vga_fb_width, init_scheduler();
vga_fb_height, enable_interrupts();
vga_fb_pitch,
vga_fb_bpp,
0, 0, 0, 0, 0, 0);
console_init();
int font_loaded = set_console_font("/fonts/cp850-8x16.psf");
if (!font_loaded) {
#ifdef SERIAL_DBG
print_serial("failed to load console font");
#endif
}
test_draw_vertical_line(100, 100, 150, 0xFFFFFFFF);
return;
kprintf("basic initializations complete\n");
vfs_node_t* vfs_root = vfs_create_root(); vfs_node_t* vfs_root = vfs_create_root();
vfs_node_t* initrd_root = load_initrd(); vfs_node_t* initrd_root = load_initrd();
@@ -162,22 +145,40 @@ void kmain(multiboot_info* mbi) {
return; return;
} }
vfs_node_t* vga_dev = devfs->create(devfs, "tvga");
vga_dev->write = vga_write;
vfs_node_t* kbd_dev = devfs->create(devfs, "kbd"); vfs_node_t* kbd_dev = devfs->create(devfs, "kbd");
kbd_dev->read = kbd_read; kbd_dev->read = kbd_read;
vfs_node_t* vga_dev = devfs->create(devfs, "vga");
vga_init(vga_dev,
vga_fb_address,
vga_fb_width,
vga_fb_height,
vga_fb_pitch,
vga_fb_bpp);
kprintf("vga initialized\n");
vfs_node_t* dev = vfs_find("/dev"); vfs_node_t* dev = vfs_find("/dev");
if (dev) { if (!dev) {
dev->mnt = devfs; kprintf("failed to find dev mnt point\n");
return;
} }
disable_interrupts(); dev->mnt = devfs;
init_scheduler(); kprintf("mounted devfs\n");
enable_interrupts();
kprintf("loading terminal program\n"); console_init();
kprintf("kernel console initialized\n");
int font_loaded = set_console_font("/fonts/kernel_font.psf");
if (!font_loaded) {
kprintf("failed to load console font\n");
}
kprintf("console font set\n");
kprintf("basic initializations complete. check serial for details\n");
kprintf("starting rockos\n");
load_root_program("/bin/vga_text_term.elf"); load_root_program("/bin/vga_text_term.elf");
kprintf("kernel going to sleep...\n"); kprintf("kernel going to sleep...\n");

View File

@@ -1,5 +1,8 @@
#include "drivers/serial/serial.h"
#include <lib/console.h> #include <lib/console.h>
#include <lib/font.h> #include <lib/font.h>
#include <lib/print.h>
#include <drivers/vga/vga.h> #include <drivers/vga/vga.h>
@@ -7,10 +10,13 @@ static psf_font_t* font;
static uint32_t console_row; static uint32_t console_row;
static uint32_t console_col; static uint32_t console_col;
static uint32_t console_width;
static uint32_t console_height;
static uint32_t console_text_color; static uint32_t console_text_color;
static uint32_t console_backgrnd_color; static uint32_t console_backgrnd_color;
static void write_vga_char(char c) { static void write_vga_char(char c) {
print_serial("write_vga_char invoked\r\n");
uint32_t vga_pitch = vga_get_pitch(); uint32_t vga_pitch = vga_get_pitch();
uint8_t* glyph = (uint8_t*)font->glyphs + (c * font->hdr->charsz); uint8_t* glyph = (uint8_t*)font->glyphs + (c * font->hdr->charsz);
@@ -34,7 +40,14 @@ static void write_vga_char(char c) {
int set_console_font(const char* path) { int set_console_font(const char* path) {
font = load_font(path); font = load_font(path);
return font != NULL; if (!font) {
return 0;
}
console_width = vga_get_width() / 8;
console_height = vga_get_height() / font->hdr->charsz;
return 1;
} }
void set_console_fg(uint32_t color) { void set_console_fg(uint32_t color) {
@@ -48,10 +61,35 @@ void set_console_bg(uint32_t color) {
void console_init() { void console_init() {
console_row = 0; console_row = 0;
console_col = 0; console_col = 0;
set_console_fg(0xFFFFFFFF); set_console_fg(0xFFFFFFFF);
vga_clear_scrn(0x000000FF); set_console_bg(0xFF6c7482);
vga_clear_scrn(console_backgrnd_color);
} }
void console_putchar(char c) { void console_putchar(char c) {
if (!font) return;
if (c == '\n') {
print_serial("\r\n");
console_col = 0;
console_row++;
if (console_row >= console_height) {
console_row = 0;
}
return;
}
write_serial(c);
write_vga_char(c); write_vga_char(c);
console_col++;
if (console_col >= console_width) {
console_col = 0;
console_row++;
}
if (console_row >= console_height) {
console_row = 0;
}
} }

View File

@@ -1,18 +1,22 @@
#include "drivers/serial/serial.h"
#include "vfs.h" #include "vfs.h"
#include <lib/font.h> #include <lib/font.h>
#include <lib/memory.h> #include <lib/memory.h>
#include <lib/print.h>
#include <stddef.h> #include <stddef.h>
psf_font_t* load_font(const char* path) { psf_font_t* load_font(const char* path) {
int fd = vfs_open(path, 0); int fd = vfs_open(path, 0);
if (fd == -1) { if (fd == -1) {
kprintf("failed to open font file %s\n", path);
return NULL; return NULL;
} }
psf_hdr_t* header = kalloc(sizeof(psf_hdr_t)); psf_hdr_t* header = kalloc(sizeof(psf_hdr_t));
int rd = vfs_read(fd, header, sizeof(psf_hdr_t)); int rd = vfs_read(fd, header, sizeof(psf_hdr_t));
if (rd <= 0) { if (rd <= 0) {
kprintf("failed to read font header\n");
kfree(header); kfree(header);
return NULL; return NULL;
} }

View File

@@ -1,4 +1,5 @@
#include "print.h" #include "print.h"
#include "drivers/serial/serial.h"
#include "stream.h" #include "stream.h"
#include "tasks.h" #include "tasks.h"
@@ -13,16 +14,21 @@ extern psf_font_t* kfont;
static char* hex_chars = "0123456789abcdef"; static char* hex_chars = "0123456789abcdef";
static void kwrite(char c) {
write_serial(c);
console_putchar(c);
}
static void kprint(const char *str) { static void kprint(const char *str) {
while (*str) { while (*str) {
console_putchar(*str); kwrite(*str);
str++; str++;
} }
} }
static void kputd(int d) { static void kputd(int d) {
if (d == 0) { if (d == 0) {
console_putchar('0'); kwrite('0');
return; return;
} }
char buffer[12]; char buffer[12];
@@ -32,13 +38,13 @@ static void kputd(int d) {
d /= 10; d /= 10;
} }
for (int j = i - 1; j >= 0; j--) { for (int j = i - 1; j >= 0; j--) {
console_putchar(buffer[j]); kwrite(buffer[j]);
} }
} }
static void kputx(unsigned int x) { static void kputx(unsigned int x) {
if (x == 0) { if (x == 0) {
console_putchar('0'); kwrite('0');
return; return;
} }
char buffer[8]; char buffer[8];
@@ -49,13 +55,13 @@ static void kputx(unsigned int x) {
x >>= 4; x >>= 4;
} }
for (int j = i - 1; j >= 0; j--) { for (int j = i - 1; j >= 0; j--) {
console_putchar(buffer[j]); kwrite(buffer[j]);
} }
} }
void kputc(const char c) { void kputc(const char c) {
spin_lock(&kwrite_lock); spin_lock(&kwrite_lock);
console_putchar(c); kwrite(c);
spin_unlock(&kwrite_lock); spin_unlock(&kwrite_lock);
} }
@@ -85,20 +91,20 @@ void kprintf(const char* fmt, ...) {
} }
case 'c': { case 'c': {
int c = va_arg(args, int); int c = va_arg(args, int);
console_putchar((char)c); kwrite((char)c);
break; break;
} }
case '%': case '%':
console_putchar('%'); kwrite('%');
break; break;
default: default:
console_putchar('%'); kwrite('%');
console_putchar(*fmt); kwrite(*fmt);
break; break;
} }
fmt++; fmt++;
} else { } else {
console_putchar(*fmt); kwrite(*fmt);
fmt++; fmt++;
} }
} }

View File

@@ -240,6 +240,39 @@ static int32_t sys_waitpid(int pid, int* exit_status) {
return 1; return 1;
} }
static int32_t sys_mmap(int fd) {
if (fd < 0) {
return 0;
}
process_t* current = current_task();
if (!current) return 0;
file_t* file = current->fd_table[fd];
if (!file) return 0;
if (!(file->node->flags & VFS_CHARDEVICE)) return 0;
uint32_t map_vaddr = 0x3FF00000;
return file->node->mmap(file->node, map_vaddr);
}
static int32_t sys_ioctl(int fd, uint32_t request, void* args) {
if (fd < 0) {
return 0;
}
process_t* current = current_task();
if (!current) return 0;
file_t* file = current->fd_table[fd];
if (!file) return 0;
if (!file->node->ioctl) return 0;
return file->node->ioctl(file->node, request, args);
}
void syscall(registers_t* regs) { void syscall(registers_t* regs) {
int32_t ret; int32_t ret;
switch(regs->eax) { switch(regs->eax) {
@@ -256,6 +289,8 @@ void syscall(registers_t* regs) {
case 23: ret = sys_dup2(regs->ebx, regs->ecx); break; case 23: ret = sys_dup2(regs->ebx, regs->ecx); break;
case 24: ret = sys_lseek(regs->ebx, regs->ecx, regs->edx); break; case 24: ret = sys_lseek(regs->ebx, regs->ecx, regs->edx); break;
case 25: ret = sys_waitpid(regs->ebx, (int*)regs->ecx); break; case 25: ret = sys_waitpid(regs->ebx, (int*)regs->ecx); break;
case 26: ret = sys_mmap(regs->ebx); break;
case 27: ret = sys_ioctl(regs->ebx, regs->ecx, (void*)regs->edx); break;
default: ret = -1; default: ret = -1;
} }
regs->eax = ret; regs->eax = ret;

17
kernel/user/video.h Normal file
View File

@@ -0,0 +1,17 @@
#ifndef USER_VIDEO_H
#define USER_VIDEO_H
#include <stdint.h>
#define FBIOGET_INFO 0x1
typedef struct {
uint32_t width;
uint32_t height;
uint32_t pitch;
uint32_t bpp;
uint32_t fb_size;
} fb_info_t;
#endif

View File

@@ -15,6 +15,9 @@ struct vfs_node;
typedef uint32_t (*read_type_t)(struct vfs_node* node, uint32_t offset, uint32_t size, uint8_t* buffer); typedef uint32_t (*read_type_t)(struct vfs_node* node, uint32_t offset, uint32_t size, uint8_t* buffer);
typedef uint32_t (*write_type_t)(struct vfs_node* node, uint32_t offset, uint32_t size, uint8_t* buffer); typedef uint32_t (*write_type_t)(struct vfs_node* node, uint32_t offset, uint32_t size, uint8_t* buffer);
typedef uint32_t (*seek_type_t)(struct vfs_node* node, uint32_t offset, int whence); typedef uint32_t (*seek_type_t)(struct vfs_node* node, uint32_t offset, int whence);
typedef uint32_t (*mmap_type_t)(struct vfs_node* node, uint32_t address);
typedef uint32_t (*ioctl_type_t)(struct vfs_node* node, uint32_t request, void* arg);
typedef struct vfs_node* (*finddir_type_t)(struct vfs_node* node, const char* name); typedef struct vfs_node* (*finddir_type_t)(struct vfs_node* node, const char* name);
typedef struct vfs_node* (*mkdir_type_t)(struct vfs_node* node, const char* name); typedef struct vfs_node* (*mkdir_type_t)(struct vfs_node* node, const char* name);
typedef struct vfs_node* (*create_type_t)(struct vfs_node* node, const char* name); typedef struct vfs_node* (*create_type_t)(struct vfs_node* node, const char* name);
@@ -33,6 +36,8 @@ typedef struct vfs_node {
mkdir_type_t mkdir; mkdir_type_t mkdir;
create_type_t create; create_type_t create;
seek_type_t seek; seek_type_t seek;
mmap_type_t mmap;
ioctl_type_t ioctl;
struct vfs_node* mnt; struct vfs_node* mnt;
void* data; void* data;

View File

@@ -1,5 +1,8 @@
#include "syscall.h"
#include <unistd.h> #include <unistd.h>
#include <sys/video.h>
#define VGA_TEXT_W 80 #define VGA_TEXT_W 80
#define VGA_TEXT_H 25 #define VGA_TEXT_H 25
@@ -8,6 +11,16 @@ void term();
int ptys; int ptys;
int ptym; int ptym;
fb_info_t fb_info;
void* framebuffer_address;
int terminal_col = 0;
int terminal_row = 0;
void term_write_char(char c) {
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
(void)argc; (void)argc;
(void)argv; (void)argv;
@@ -28,42 +41,20 @@ int main(int argc, char *argv[]) {
dup2(0, 1); dup2(0, 1);
dup2(0, 2); dup2(0, 2);
term(); int vga_fd = open("/dev/vga");
if (vga_fd == -1) return 1;
int kbd_fd = open("/dev/kbd");
if (kbd_fd == -1) return 1;
int res = ioctl(vga_fd, FBIOGET_INFO, &fb_info);
if (!res) {
return 1;
}
framebuffer_address = mmap(vga_fd);
return 0; return 0;
} }
void clear(int fd) {
lseek(fd, 0, 0);
size_t bytes = VGA_TEXT_W * VGA_TEXT_H;
char c = ' ';
for (size_t i = 0; i < bytes; i++) {
write(fd, &c, 1);
}
lseek(fd, 0, 0);
}
void term() {
int vga_fd = open("/dev/tvga");
if (vga_fd == -1) return;
int kbd_fd = open("/dev/kbd");
if (kbd_fd == -1) return;
clear(vga_fd);
char c;
while (1) {
// first, get shell output
int rd = read(0, &c, 1);
if (rd > 0) {
write(vga_fd, &c, 1);
}
// then read a byte from the kbd. If we got one, pass it to the shell
rd = read(kbd_fd, &c, 1);
if (rd > 0) {
write(1, &c, 1);
}
}
}

View File

@@ -0,0 +1,16 @@
#ifndef USER_VIDEO_H
#define USER_VIDEO_H
#include <stdint.h>
#define FBIOGET_INFO 0x1
typedef struct {
uint32_t width;
uint32_t height;
uint32_t pitch;
uint32_t bpp;
uint32_t fb_size;
} fb_info_t;
#endif

View File

@@ -17,6 +17,8 @@
#define SYS_DUP2 23 #define SYS_DUP2 23
#define SYS_LSEEK 24 #define SYS_LSEEK 24
#define SYS_WAIT 25 #define SYS_WAIT 25
#define SYS_MMAP 26
#define SYS_IOCTL 27
int open(const char* path); int open(const char* path);
int write(int fd, const void *buf, size_t count); int write(int fd, const void *buf, size_t count);
@@ -25,6 +27,8 @@ int close(int fd);
int lseek(int fd, size_t offset, int whence); int lseek(int fd, size_t offset, int whence);
void* mmap(int fd);
void exit(int status) __attribute__((noreturn)); void exit(int status) __attribute__((noreturn));
void* sbrk(int32_t increment); void* sbrk(int32_t increment);
@@ -37,4 +41,6 @@ int exec(const char* path);
int dup2(int src, int dst); int dup2(int src, int dst);
int waitpid(int pid, int* status); int waitpid(int pid, int* status);
int ioctl(int fd, uint32_t request, void* arg);
#endif #endif

View File

@@ -74,3 +74,11 @@ void* sbrk(int32_t increment) {
int brk(void *addr) { int brk(void *addr) {
return syscall1(SYS_BRK, (uint32_t)addr); return syscall1(SYS_BRK, (uint32_t)addr);
} }
void* mmap(int fd) {
return (void*)syscall1(SYS_MMAP, fd);
}
int ioctl(int fd, uint32_t request, void* arg) {
return syscall3(SYS_IOCTL, fd, request, arg);
}