diff --git a/Makefile b/Makefile index 694385f..bad4f80 100644 --- 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 index 3b93a81..a0d44dd 100644 --- 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 index 46663b3..9cf1715 100644 --- a/kernel/drivers/video/vga.c +++ b/kernel/drivers/video/vga.c @@ -1,61 +1,118 @@ #include -/* #include */ -#include -/* 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; +} + +// Write vga registers for mode change +static void +write_regs(uint8_t *regs) +{ + 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_setcolor(uint8_t color) +vga_set_mode_13h(void) { - term_color = 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_putentryat(char c, uint8_t color, size_t x, size_t y) +vga_put_pixel(uint16_t x, uint16_t y, uint8_t color) { - const size_t index = y * VGA_HEIGHT + x; - term_buf[index] = vga_entry(c, color); + // 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_putchar(char c) +vga_clear_screen(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; - } - } -} - -void -term_writestr(const char* data) -{ - 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 new file mode 100644 index 0000000..5565817 Binary files /dev/null and b/kernel/drivers/video/vga.o differ diff --git a/kernel/include/drivers/video/vga.h b/kernel/include/drivers/video/vga.h index 7dc2869..8940ece 100644 --- a/kernel/include/drivers/video/vga.h +++ b/kernel/include/drivers/video/vga.h @@ -2,49 +2,30 @@ #define VGA_H #include -#include -/* 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 deleted file mode 100644 index 8469e6e..0000000 --- a/kernel/include/fb.h +++ /dev/null @@ -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 - -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 new file mode 100644 index 0000000..790ba5e --- /dev/null +++ b/kernel/include/gdt.h @@ -0,0 +1,28 @@ +#include + +#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 index af2b5d9..527c081 100644 --- a/kernel/init/kernel.c +++ b/kernel/init/kernel.c @@ -1,12 +1,15 @@ +#include #include -/* #include */ +#include #include #include -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 new file mode 100644 index 0000000..5631da2 Binary files /dev/null and b/kernel/init/kernel.o differ diff --git a/kernel/klibc/stdio.o b/kernel/klibc/stdio.o new file mode 100644 index 0000000..7cac39c Binary files /dev/null and b/kernel/klibc/stdio.o differ diff --git a/kernel/klibc/string.o b/kernel/klibc/string.o new file mode 100644 index 0000000..fae87dc Binary files /dev/null and b/kernel/klibc/string.o differ diff --git a/kernel/x86/gdt.c b/kernel/x86/gdt.c new file mode 100644 index 0000000..0d57583 --- /dev/null +++ b/kernel/x86/gdt.c @@ -0,0 +1,73 @@ +#include + +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 new file mode 100644 index 0000000..12e173d Binary files /dev/null and b/kernel/x86/gdt.o differ diff --git a/scripts/limine-git.sh b/scripts/limine-git.sh new file mode 100755 index 0000000..6bc1771 --- /dev/null +++ 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