commit 41b34d2a9d4ac650d491bd0bc77ebf62ae648211
parent b08b0728ae5e297d794a02297f01eb76aa8fb909
Author: cowmonk <cowmonk@based.pt>
Date: Fri, 18 Jul 2025 23:50:07 -0700
cowos attempted gdt, but at least we have vga drivers now
Diffstat:
14 files changed, 250 insertions(+), 137 deletions(-)
diff --git a/Makefile b/Makefile
@@ -15,14 +15,7 @@ kernel:
make -C ./kernel/ all
limine: kernel
- git clone https://github.com/limine-bootloader/limine.git --branch=v9.x-binary --depth=1
- make -C limine
-
- cp -v limine/limine-bios.sys limine/limine-bios-cd.bin \
- limine/limine-uefi-cd.bin isodir/boot/limine/
-
- cp -v limine/BOOTX64.EFI isodir/EFI/BOOT/
- cp -v limine/BOOTIA32.EFI isodir/EFI/BOOT/
+ ./scripts/limine-git.sh
clean:
rm cowos.iso
diff --git a/README.md b/README.md
@@ -24,3 +24,6 @@ make
# Credits
- [Limine](https://github.com/limine-bootloader/limine): modern, advanced, portable, multiprotocol bootloader and boot manager.
+
+## People
+- micl: random guy on the interweb in the LHL discord server gave me a free vga driver to use lol
diff --git a/kernel/drivers/video/vga.c b/kernel/drivers/video/vga.c
@@ -1,61 +1,118 @@
#include <drivers/video/vga.h>
-/* #include <bootloader.h> */
-#include <string.h>
-/* for frame buffer
-static volatile struct limine_framebuffer_request limineFBreq = {
- .id = LIMINE_FRAMEBUFFER_REQUEST, .revision = 0};
-*/
-
-size_t term_row;
-size_t term_col;
-uint8_t term_color;
-uint16_t* term_buf = (uint16_t*)VGA_MEMORY;
-
-void
-term_init(void)
+// Helper functions for port IO
+static inline void
+outb(uint16_t port, uint8_t val)
{
- term_row = 0;
- term_col = 0;
- term_color = vga_entry_color(VGA_COLOR_WHITE, VGA_COLOR_BLACK);
+ __asm__ volatile ("outb %0, %1" : : "a"(val), "Nd"(port));
+}
- for (size_t y = 0; y < VGA_HEIGHT; y++) {
- for (size_t x = 0; x < VGA_WIDTH; x++) {
- const size_t index = y * VGA_WIDTH + x;
- term_buf[index] = vga_entry(' ', term_color);
- }
- }
+static inline uint8_t
+inb(uint16_t port)
+{
+ uint8_t ret;
+ __asm__ volatile ("inb %1, %0" : "=a"(ret) : "Nd"(port));
+ return ret;
}
-void
-term_setcolor(uint8_t color)
+// Write vga registers for mode change
+static void
+write_regs(uint8_t *regs)
{
- term_color = color;
+ unsigned i;
+
+ // Write misc output register
+ outb(VGA_MISC_WRITE, *regs);
+ regs++;
+
+ // Write sequencer registers (5 registers)
+ for (i = 0; i < 5; i++) {
+ outb(VGA_SEQ_INDEX, i);
+ outb(VGA_SEQ_DATA, *regs);
+ regs++;
+ }
+
+ // Unlock CRTC registers 0-7 by clearing protect bit
+ outb(VGA_CRTC_INDEX, 0x03);
+ outb(VGA_CRTC_DATA, inb(VGA_CRTC_DATA) | 0x80);
+ outb(VGA_CRTC_INDEX, 0x11);
+ outb(VGA_CRTC_DATA, inb(VGA_CRTC_DATA) & ~0x80);
+
+ // Update the register values to match
+ regs[0x03] = regs[0x03] | 0x80;
+ regs[0x11] = regs[0x11] & ~0x80;
+
+ // Write CRTC registers (25 registers)
+ for (i = 0; i < 25; i++) {
+ outb(VGA_CRTC_INDEX, i);
+ outb(VGA_CRTC_DATA, *regs);
+ regs++;
+ }
+
+ // Write graphics controller registers (9 registers)
+ for (i = 0; i < 9; i++) {
+ outb(VGA_GC_INDEX, i);
+ outb(VGA_GC_DATA, *regs);
+ regs++;
+ }
+
+ // Write attribute controller registers (21 registers)
+ for (i = 0; i < 21; i++) {
+ inb(VGA_INSTAT_READ); // Reset flip-flop
+ outb(VGA_AC_INDEX, i);
+ outb(VGA_AC_WRITE, *regs);
+ regs++;
+ }
+
+ // Enable video display
+ inb(VGA_INSTAT_READ);
+ outb(VGA_AC_INDEX, 0x20);
}
void
-term_putentryat(char c, uint8_t color, size_t x, size_t y)
+vga_set_mode_13h(void)
{
- const size_t index = y * VGA_HEIGHT + x;
- term_buf[index] = vga_entry(c, color);
+ // Register values for VGA mode 13h (320x200, 256 colors)
+ // Order: Misc, Seq[5], CRTC[25], GC[9], AC[21]
+ static uint8_t mode_320x200x256[] = {
+ // Misc output register
+ 0x63,
+ // Sequencer registers
+ 0x03, 0x01, 0x0F, 0x00, 0x0E,
+ // CRTC registers
+ 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F,
+ 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x9C, 0x0E, 0x8F, 0x28, 0x40, 0x96, 0xB9, 0xA3,
+ 0xFF,
+ // Graphics controller registers
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
+ 0xFF,
+ // Attribute controller registers
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x41, 0x00, 0x0F, 0x00, 0x00
+ };
+
+ write_regs(mode_320x200x256);
}
void
-term_putchar(char c)
+vga_put_pixel(uint16_t x, uint16_t y, uint8_t color)
{
- term_putentryat(c, term_color, term_col, term_row);
- if (++term_col == VGA_WIDTH) {
- term_col = 0;
- if (++term_row == VGA_HEIGHT) {
- term_row = 0;
- }
- }
+ // check bounds
+ if (x >= VGA_WIDTH || y >= VGA_HEIGHT) return;
+
+ // Direct write to video memory: offset = y * 320 + x
+ uint8_t *vga = (uint8_t *)VGA_GRAPHICS_BUFFER;
+ vga[y * VGA_WIDTH + x] = color;
}
void
-term_writestr(const char* data)
+vga_clear_screen(uint8_t color)
{
- for (size_t i = 0; data[i] != '\0'; i++) {
- term_putchar(data[i]);
- }
+ uint8_t *vga = (uint8_t *)VGA_GRAPHICS_BUFFER;
+ // fill entire buffer (64k pixels)
+ for (int i = 0; i < VGA_WIDTH * VGA_HEIGHT; i++) {
+ vga[i] = color;
+ }
}
diff --git a/kernel/drivers/video/vga.o b/kernel/drivers/video/vga.o
Binary files differ.
diff --git a/kernel/include/drivers/video/vga.h b/kernel/include/drivers/video/vga.h
@@ -2,49 +2,30 @@
#define VGA_H
#include <stdint.h>
-#include <stddef.h>
-/* hardware text mode const */
-enum vga_color {
- VGA_COLOR_BLACK = 0,
- VGA_COLOR_BLUE = 1,
- VGA_COLOR_GREEN = 2,
- VGA_COLOR_CYAN = 3,
- VGA_COLOR_RED = 4,
- VGA_COLOR_MAGENTA = 5,
- VGA_COLOR_BROWN = 6,
- VGA_COLOR_LIGHT_GREY = 7,
- VGA_COLOR_DARK_GREY = 8,
- VGA_COLOR_LIGHT_BLUE = 9,
- VGA_COLOR_LIGHT_GREEN = 10,
- VGA_COLOR_LIGHT_CYAN = 11,
- VGA_COLOR_LIGHT_RED = 12,
- VGA_COLOR_LIGHT_MAGENTA = 13,
- VGA_COLOR_LIGHT_BROWN = 14,
- VGA_COLOR_WHITE = 15,
-};
+// VGA mem addr
+#define VGA_TEXT_BUFFER 0xB8000 // Text mode video memory
+#define VGA_GRAPHICS_BUFFER 0xA0000 // Graphics mode video memory
-static inline uint8_t
-vga_entry_color(enum vga_color fg, enum vga_color bg)
-{
- return fg | bg << 4;
-}
+// VGA mode 13h dimensions
+#define VGA_WIDTH 320
+#define VGA_HEIGHT 200
-static inline uint16_t
-vga_entry(unsigned char uc, uint8_t color)
-{
- return (uint16_t) uc | (uint16_t) color << 8;
-}
+// VGA register IO ports
+#define VGA_AC_INDEX 0x3C0 // attribute controller index
+#define VGA_AC_WRITE 0x3C0 // attribute controller write
+#define VGA_AC_READ 0x3C1 // attribute controller read
+#define VGA_MISC_WRITE 0x3C2 // miscellaneous output register
+#define VGA_SEQ_INDEX 0x3C4 // sequencer index
+#define VGA_SEQ_DATA 0x3C5 // sequencer data
+#define VGA_GC_INDEX 0x3CE // graphics controller index
+#define VGA_GC_DATA 0x3CF // graphics controller data
+#define VGA_CRTC_INDEX 0x3D4 // CRT controller index
+#define VGA_CRTC_DATA 0x3D5 // CRT controller data
+#define VGA_INSTAT_READ 0x3DA // input status read
-/* using mode 3 of VGA 80x25 */
-#define VGA_WIDTH 80
-#define VGA_HEIGHT 25
-#define VGA_MEMORY 0xA0000 /* VGA memory location */
+void vga_set_mode_13h(void);
+void vga_put_pixel(uint16_t x, uint16_t y, uint8_t color);
+void vga_clear_screen(uint8_t color);
-void term_init(void);
-void term_setcolor(uint8_t color);
-void term_putentryat(char c, uint8_t color, size_t x, size_t y);
-void term_putchar(char c);
-void term_writestr(const char* data);
-
-#endif // VGA_H
+#endif
diff --git a/kernel/include/fb.h b/kernel/include/fb.h
@@ -1,22 +0,0 @@
-#ifndef FB_H
-#define FB_H
-
-/* *pixel = vram + y*pitch + x*pixelwidth */
-
-/*
- | width | how many pixels you have on a horizontal line |
- |===========================================================================|
- | height | how many horizontal lines of pixels are present |
- |===========================================================================|
- | pitch | how many bytes of VRAM you should skip to go one pixel down |
- |===========================================================================|
- | depth | how many bits of color you have |
- |===========================================================================|
- | pixelwidth | how many bytes of VRAM you should skip to go one pixel right |
-*/
-
-#include <klibc/types.h>
-
-void putpixel(int pos_x, int pos_y, unsigned char VGA_COLOR);
-
-#endif /* FB_H */
diff --git a/kernel/include/gdt.h b/kernel/include/gdt.h
@@ -0,0 +1,28 @@
+#include <stdint.h>
+
+#ifndef GDT_H
+#define GDT_H
+
+typedef struct GDTEntry {
+ uint16_t limit;
+ uint16_t base_low;
+ uint16_t base_mid;
+ uint8_t base_high;
+ uint8_t access;
+ uint8_t granularity;
+} __attribute__((packed)) GDTEntry;
+
+typedef struct GDTPtr {
+ uint16_t limit;
+ uint64_t base;
+} __attribute__((packed)) GDTPtr;
+
+#define GDT_NUM_ENTRIES 5 /* including null descriptor */
+#define GDT_KERNEL_CODE 0x08
+#define GDT_KERNEL_DATA 0x10
+#define GDT_USER_CODE 0x18
+#define GDT_USER_DATA 0x20
+
+void initGDT();
+
+#endif /* GDT_H */
diff --git a/kernel/init/kernel.c b/kernel/init/kernel.c
@@ -1,12 +1,15 @@
+#include <gdt.h>
#include <klibc/string.h>
-/* #include <drivers/video/vga.h> */
+#include <drivers/video/vga.h>
#include <stddef.h>
#include <bootloader.h>
-static void hcf(void) {
- for (;;) {
- __asm__("hlt");
- }
+static void
+hcf(void)
+{
+ for (;;) {
+ __asm__("hlt");
+ }
}
void
@@ -14,27 +17,10 @@ kernel_main(void)
{
/* Make sure the bootloader understands our base revision */
if (LIMINE_BASE_REVISION_SUPPORTED == 0) hcf();
+
+ vga_set_mode_13h();
- /* ensure a framebuffer */
- if (framebuffer_request.response == NULL
- || framebuffer_request.response->framebuffer_count < 1) hcf();
-
- /* fetch the first framebuffer */
- struct limine_framebuffer *framebuffer = framebuffer_request.response->framebuffers[0];
-
- /* assume framebuffer model is RGB w/32-bit pixels */
- for (size_t i = 0; i < 100; i++) {
- volatile uint32_t *fb_ptr = framebuffer->address;
- fb_ptr[i * (framebuffer->pitch / 4) + i] = 0xffffff;
- }
-
- /* need to get an actual framebuffer driver working before we can use vga */
-
- /*
- term_init();
-
- term_writestr("Hello World!");
- */
+ /* initGDT(); */
/* done so now hang */
hcf();
diff --git a/kernel/init/kernel.o b/kernel/init/kernel.o
Binary files differ.
diff --git a/kernel/klibc/stdio.o b/kernel/klibc/stdio.o
Binary files differ.
diff --git a/kernel/klibc/string.o b/kernel/klibc/string.o
Binary files differ.
diff --git a/kernel/x86/gdt.c b/kernel/x86/gdt.c
@@ -0,0 +1,73 @@
+#include <gdt.h>
+
+static GDTEntry descriptors[5];
+static GDTPtr gdtptr;
+
+void
+gdt_reload()
+{
+ asm volatile("lgdt %0\n\t"
+ "push $0x28\n\t"
+ "lea 1f(%%rip), %%rax\n\t"
+ "push %%rax\n\t"
+ "lretq\n\t"
+ "1:\n\t"
+ "mov $0x30, %%eax\n\t"
+ "mov %%eax, %%ds\n\t"
+ "mov %%eax, %%es\n\t"
+ "mov %%eax, %%fs\n\t"
+ "mov %%eax, %%gs\n\t"
+ "mov %%eax, %%ss\n\t"
+ :
+ : "m"(gdtptr)
+ : "rax", "memory");
+}
+
+void
+initGDT()
+{
+ /* null descriptor (0) */
+ descriptors[0].limit = 0;
+ descriptors[0].base_low = 0;
+ descriptors[0].base_mid = 0;
+ descriptors[0].access = 0;
+ descriptors[0].granularity = 0;
+ descriptors[0].base_high = 0;
+
+ /* kernel code 64 (40) */
+ descriptors[1].limit = 0;
+ descriptors[1].base_low = 0;
+ descriptors[1].base_mid = 0;
+ descriptors[1].access = 0b10011010;
+ descriptors[1].granularity = 0b00100000;
+ descriptors[1].base_high = 0;
+
+ /* kernel data 64 (48) */
+ descriptors[2].limit = 0;
+ descriptors[2].base_low = 0;
+ descriptors[2].base_mid = 0;
+ descriptors[2].access = 0b10010010;
+ descriptors[2].granularity = 0;
+ descriptors[2].base_high = 0;
+
+ // user code 64 (72)
+ descriptors[3].limit = 0;
+ descriptors[3].base_low = 0;
+ descriptors[3].base_mid = 0;
+ descriptors[3].access = 0b11111010;
+ descriptors[3].granularity = 0b00100000;
+ descriptors[3].base_high = 0;
+
+ // user data 64. (80)
+ descriptors[4].limit = 0;
+ descriptors[4].base_low = 0;
+ descriptors[4].base_mid = 0;
+ descriptors[4].access = 0b11110010;
+ descriptors[4].granularity = 0;
+ descriptors[4].base_high = 0;
+
+ gdtptr.limit = sizeof(descriptors) - 1;
+ gdtptr.base = (uint64_t)&descriptors;
+
+ gdt_reload();
+}
diff --git a/kernel/x86/gdt.o b/kernel/x86/gdt.o
Binary files differ.
diff --git a/scripts/limine-git.sh b/scripts/limine-git.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+if [ ! -d ./limine/ ]; then
+ git clone https://github.com/limine-bootloader/limine.git --branch=v9.x-binary --depth=1
+ make -C limine
+
+ cp -v limine/limine-bios.sys limine/limine-bios-cd.bin \
+ limine/limine-uefi-cd.bin isodir/boot/limine/
+
+ mkdir -p isodir/EFI/BOOT
+
+ cp -v limine/BOOTX64.EFI isodir/EFI/BOOT/
+ cp -v limine/BOOTIA32.EFI isodir/EFI/BOOT/
+fi