mirror of
https://github.com/cowmonk/cowos.git
synced 2025-10-27 14:33:27 +00:00
cowos attempted gdt, but at least we have vga drivers now
This commit is contained in:
parent
b08b0728ae
commit
41b34d2a9d
14 changed files with 253 additions and 140 deletions
9
Makefile
9
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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
BIN
kernel/drivers/video/vga.o
Normal file
BIN
kernel/drivers/video/vga.o
Normal file
Binary file not shown.
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
28
kernel/include/gdt.h
Normal file
28
kernel/include/gdt.h
Normal file
|
|
@ -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 */
|
||||
|
|
@ -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
|
||||
|
|
@ -15,26 +18,9 @@ kernel_main(void)
|
|||
/* Make sure the bootloader understands our base revision */
|
||||
if (LIMINE_BASE_REVISION_SUPPORTED == 0) hcf();
|
||||
|
||||
/* ensure a framebuffer */
|
||||
if (framebuffer_request.response == NULL
|
||||
|| framebuffer_request.response->framebuffer_count < 1) hcf();
|
||||
vga_set_mode_13h();
|
||||
|
||||
/* 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();
|
||||
|
|
|
|||
BIN
kernel/init/kernel.o
Normal file
BIN
kernel/init/kernel.o
Normal file
Binary file not shown.
BIN
kernel/klibc/stdio.o
Normal file
BIN
kernel/klibc/stdio.o
Normal file
Binary file not shown.
BIN
kernel/klibc/string.o
Normal file
BIN
kernel/klibc/string.o
Normal file
Binary file not shown.
73
kernel/x86/gdt.c
Normal file
73
kernel/x86/gdt.c
Normal file
|
|
@ -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();
|
||||
}
|
||||
BIN
kernel/x86/gdt.o
Normal file
BIN
kernel/x86/gdt.o
Normal file
Binary file not shown.
14
scripts/limine-git.sh
Executable file
14
scripts/limine-git.sh
Executable file
|
|
@ -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
|
||||
Loading…
Add table
Add a link
Reference in a new issue