From b58863425322610aca58a412b2face2d22c0a048 Mon Sep 17 00:00:00 2001 From: slinky55 Date: Thu, 16 Jul 2026 14:44:08 -0500 Subject: [PATCH] working on exposing vga to userspace --- .../fonts/{cp850-8x16.psf => kernel_font.psf} | Bin kernel/drivers/cpio/cpio.c | 3 + kernel/drivers/serial/serial.c | 1 + kernel/drivers/vga/vga.c | 95 ++++++++---------- kernel/drivers/vga/vga.h | 12 +-- kernel/kmain.c | 59 +++++------ kernel/lib/console.c | 42 +++++++- kernel/lib/font.c | 4 + kernel/lib/print.c | 28 ++++-- kernel/syscall.c | 35 +++++++ kernel/user/video.h | 17 ++++ kernel/vfs.h | 5 + programs/vga_text_term/main.c | 59 +++++------ rocklibc/include/sys/video.h | 16 +++ rocklibc/include/syscall.h | 6 ++ rocklibc/src/syscall.c | 8 ++ 16 files changed, 251 insertions(+), 139 deletions(-) rename initrd/fonts/{cp850-8x16.psf => kernel_font.psf} (100%) create mode 100644 kernel/user/video.h create mode 100644 rocklibc/include/sys/video.h diff --git a/initrd/fonts/cp850-8x16.psf b/initrd/fonts/kernel_font.psf similarity index 100% rename from initrd/fonts/cp850-8x16.psf rename to initrd/fonts/kernel_font.psf diff --git a/kernel/drivers/cpio/cpio.c b/kernel/drivers/cpio/cpio.c index 53dfbd6..9f942a2 100644 --- a/kernel/drivers/cpio/cpio.c +++ b/kernel/drivers/cpio/cpio.c @@ -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) { + if (strcmp(path, "fonts") == 0) { + kprintf("found fonts folder\n"); + } vfs_node_t* current = root_node; char path_cpy[256]; diff --git a/kernel/drivers/serial/serial.c b/kernel/drivers/serial/serial.c index ec3f407..7e4a26b 100644 --- a/kernel/drivers/serial/serial.c +++ b/kernel/drivers/serial/serial.c @@ -9,6 +9,7 @@ int is_transmit_empty() { void write_serial(char a) { while (is_transmit_empty() == 0); + if (a == '\n') outb(COM1, '\r'); outb(COM1, a); } diff --git a/kernel/drivers/vga/vga.c b/kernel/drivers/vga/vga.c index a32836d..4344728 100644 --- a/kernel/drivers/vga/vga.c +++ b/kernel/drivers/vga/vga.c @@ -1,3 +1,4 @@ +#include "vfs.h" #include #include @@ -9,6 +10,8 @@ #include #include +#include + static uint32_t framebuffer_address; static uint32_t framebuffer_width; 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_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( + vfs_node_t* dev, uint32_t fb_paddr, uint32_t fb_width, uint32_t fb_height, uint32_t fb_pitch, - 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 + uint8_t fb_bpp ) { - framebuffer_address = VGA_FRAMEBUFFER; - - red_mask_sz = _red_mask_sz; - red_field_pos = _red_field_pos; - green_mask_sz = _green_mask_sz; - green_field_pos = _green_field_pos; - 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"); + framebuffer_address = fb_paddr; + framebuffer_width = fb_width; + framebuffer_height = fb_height; + framebuffer_total_pixels = framebuffer_width * framebuffer_height; + framebuffer_pitch = fb_pitch; + framebuffer_bpp = fb_bpp; uint32_t fb_size_bytes = fb_height * fb_pitch; 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); } - 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); + + dev->flags = VFS_CHARDEVICE; + dev->mmap = vga_mmap; + dev->ioctl = vga_ioctl; } uint32_t vga_get_framebuffer() { - return framebuffer_address; + return VGA_FRAMEBUFFER; } 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; - } - } -} \ No newline at end of file diff --git a/kernel/drivers/vga/vga.h b/kernel/drivers/vga/vga.h index 28a08bd..1ea8906 100644 --- a/kernel/drivers/vga/vga.h +++ b/kernel/drivers/vga/vga.h @@ -17,19 +17,15 @@ extern vga_color_t VGA_COLOR_BLACK; extern vga_color_t VGA_COLOR_RED; extern vga_color_t VGA_COLOR_GREEN; extern vga_color_t VGA_COLOR_BLUE; +extern vga_color_t VGA_COLOR_ROCKOS; void vga_init( + vfs_node_t* dev, uint32_t fb_paddr, uint32_t fb_width, uint32_t fb_height, uint32_t fb_pitch, - 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 + uint8_t fb_bpp ); 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); -void test_draw_vertical_line(uint32_t x, uint32_t y_start, uint32_t y_end, uint32_t color); - #endif \ No newline at end of file diff --git a/kernel/kmain.c b/kernel/kmain.c index a67fcb9..b1d6f26 100644 --- a/kernel/kmain.c +++ b/kernel/kmain.c @@ -125,26 +125,9 @@ void kmain(multiboot_info* mbi) { init_pmm((void*)mmap_virtual_addr, mbi->mmap_length); init_page_tables(); - vga_init(vga_fb_address, - vga_fb_width, - vga_fb_height, - 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"); + disable_interrupts(); + init_scheduler(); + enable_interrupts(); vfs_node_t* vfs_root = vfs_create_root(); vfs_node_t* initrd_root = load_initrd(); @@ -162,22 +145,40 @@ void kmain(multiboot_info* mbi) { return; } - vfs_node_t* vga_dev = devfs->create(devfs, "tvga"); - vga_dev->write = vga_write; - vfs_node_t* kbd_dev = devfs->create(devfs, "kbd"); 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"); - if (dev) { - dev->mnt = devfs; + if (!dev) { + kprintf("failed to find dev mnt point\n"); + return; } - disable_interrupts(); - init_scheduler(); - enable_interrupts(); + dev->mnt = devfs; + kprintf("mounted devfs\n"); + + console_init(); + kprintf("kernel console initialized\n"); - kprintf("loading terminal program\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"); kprintf("kernel going to sleep...\n"); diff --git a/kernel/lib/console.c b/kernel/lib/console.c index b04a1df..e8afdad 100644 --- a/kernel/lib/console.c +++ b/kernel/lib/console.c @@ -1,5 +1,8 @@ +#include "drivers/serial/serial.h" + #include #include +#include #include @@ -7,10 +10,13 @@ static psf_font_t* font; static uint32_t console_row; 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_backgrnd_color; static void write_vga_char(char c) { + print_serial("write_vga_char invoked\r\n"); uint32_t vga_pitch = vga_get_pitch(); 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) { 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) { @@ -48,10 +61,35 @@ void set_console_bg(uint32_t color) { void console_init() { console_row = 0; console_col = 0; + set_console_fg(0xFFFFFFFF); - vga_clear_scrn(0x000000FF); + set_console_bg(0xFF6c7482); + vga_clear_scrn(console_backgrnd_color); } 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); + + console_col++; + if (console_col >= console_width) { + console_col = 0; + console_row++; + } + + if (console_row >= console_height) { + console_row = 0; + } } \ No newline at end of file diff --git a/kernel/lib/font.c b/kernel/lib/font.c index e39ea6c..94c6267 100644 --- a/kernel/lib/font.c +++ b/kernel/lib/font.c @@ -1,18 +1,22 @@ +#include "drivers/serial/serial.h" #include "vfs.h" #include #include +#include #include psf_font_t* load_font(const char* path) { int fd = vfs_open(path, 0); if (fd == -1) { + kprintf("failed to open font file %s\n", path); return NULL; } psf_hdr_t* header = kalloc(sizeof(psf_hdr_t)); int rd = vfs_read(fd, header, sizeof(psf_hdr_t)); if (rd <= 0) { + kprintf("failed to read font header\n"); kfree(header); return NULL; } diff --git a/kernel/lib/print.c b/kernel/lib/print.c index f7ded6b..4be6dce 100644 --- a/kernel/lib/print.c +++ b/kernel/lib/print.c @@ -1,4 +1,5 @@ #include "print.h" +#include "drivers/serial/serial.h" #include "stream.h" #include "tasks.h" @@ -13,16 +14,21 @@ extern psf_font_t* kfont; static char* hex_chars = "0123456789abcdef"; +static void kwrite(char c) { + write_serial(c); + console_putchar(c); +} + static void kprint(const char *str) { while (*str) { - console_putchar(*str); + kwrite(*str); str++; } } static void kputd(int d) { if (d == 0) { - console_putchar('0'); + kwrite('0'); return; } char buffer[12]; @@ -32,13 +38,13 @@ static void kputd(int d) { d /= 10; } for (int j = i - 1; j >= 0; j--) { - console_putchar(buffer[j]); + kwrite(buffer[j]); } } static void kputx(unsigned int x) { if (x == 0) { - console_putchar('0'); + kwrite('0'); return; } char buffer[8]; @@ -49,13 +55,13 @@ static void kputx(unsigned int x) { x >>= 4; } for (int j = i - 1; j >= 0; j--) { - console_putchar(buffer[j]); + kwrite(buffer[j]); } } void kputc(const char c) { spin_lock(&kwrite_lock); - console_putchar(c); + kwrite(c); spin_unlock(&kwrite_lock); } @@ -85,20 +91,20 @@ void kprintf(const char* fmt, ...) { } case 'c': { int c = va_arg(args, int); - console_putchar((char)c); + kwrite((char)c); break; } case '%': - console_putchar('%'); + kwrite('%'); break; default: - console_putchar('%'); - console_putchar(*fmt); + kwrite('%'); + kwrite(*fmt); break; } fmt++; } else { - console_putchar(*fmt); + kwrite(*fmt); fmt++; } } diff --git a/kernel/syscall.c b/kernel/syscall.c index 75f497f..4804e8c 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -240,6 +240,39 @@ static int32_t sys_waitpid(int pid, int* exit_status) { 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) { int32_t ret; switch(regs->eax) { @@ -256,6 +289,8 @@ void syscall(registers_t* regs) { case 23: ret = sys_dup2(regs->ebx, regs->ecx); 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 26: ret = sys_mmap(regs->ebx); break; + case 27: ret = sys_ioctl(regs->ebx, regs->ecx, (void*)regs->edx); break; default: ret = -1; } regs->eax = ret; diff --git a/kernel/user/video.h b/kernel/user/video.h new file mode 100644 index 0000000..a42a03c --- /dev/null +++ b/kernel/user/video.h @@ -0,0 +1,17 @@ +#ifndef USER_VIDEO_H +#define USER_VIDEO_H + +#include + +#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 \ No newline at end of file diff --git a/kernel/vfs.h b/kernel/vfs.h index 365e8e7..d4d90bc 100644 --- a/kernel/vfs.h +++ b/kernel/vfs.h @@ -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 (*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 (*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* (*mkdir_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; create_type_t create; seek_type_t seek; + mmap_type_t mmap; + ioctl_type_t ioctl; struct vfs_node* mnt; void* data; diff --git a/programs/vga_text_term/main.c b/programs/vga_text_term/main.c index 7c2f108..d8306d3 100644 --- a/programs/vga_text_term/main.c +++ b/programs/vga_text_term/main.c @@ -1,5 +1,8 @@ +#include "syscall.h" #include +#include + #define VGA_TEXT_W 80 #define VGA_TEXT_H 25 @@ -8,6 +11,16 @@ void term(); int ptys; 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[]) { (void)argc; (void)argv; @@ -28,42 +41,20 @@ int main(int argc, char *argv[]) { dup2(0, 1); dup2(0, 2); - term(); - - 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 vga_fd = open("/dev/vga"); + if (vga_fd == -1) return 1; int kbd_fd = open("/dev/kbd"); - if (kbd_fd == -1) return; + if (kbd_fd == -1) return 1; - 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); - } + int res = ioctl(vga_fd, FBIOGET_INFO, &fb_info); + if (!res) { + return 1; } + + framebuffer_address = mmap(vga_fd); + + + + return 0; } \ No newline at end of file diff --git a/rocklibc/include/sys/video.h b/rocklibc/include/sys/video.h new file mode 100644 index 0000000..d87e23c --- /dev/null +++ b/rocklibc/include/sys/video.h @@ -0,0 +1,16 @@ +#ifndef USER_VIDEO_H +#define USER_VIDEO_H + +#include + +#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 \ No newline at end of file diff --git a/rocklibc/include/syscall.h b/rocklibc/include/syscall.h index 1ff4d32..d17ef2c 100644 --- a/rocklibc/include/syscall.h +++ b/rocklibc/include/syscall.h @@ -17,6 +17,8 @@ #define SYS_DUP2 23 #define SYS_LSEEK 24 #define SYS_WAIT 25 +#define SYS_MMAP 26 +#define SYS_IOCTL 27 int open(const char* path); 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); +void* mmap(int fd); + void exit(int status) __attribute__((noreturn)); void* sbrk(int32_t increment); @@ -37,4 +41,6 @@ int exec(const char* path); int dup2(int src, int dst); int waitpid(int pid, int* status); +int ioctl(int fd, uint32_t request, void* arg); + #endif \ No newline at end of file diff --git a/rocklibc/src/syscall.c b/rocklibc/src/syscall.c index 87f67ff..db175a3 100644 --- a/rocklibc/src/syscall.c +++ b/rocklibc/src/syscall.c @@ -73,4 +73,12 @@ void* sbrk(int32_t increment) { int brk(void *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); } \ No newline at end of file