From 9d94299fb1812ae883cfc877224d82f367f3ef9f Mon Sep 17 00:00:00 2001 From: Justus Wolff Date: Mon, 6 Apr 2026 00:48:38 +0200 Subject: [PATCH] trying to make the keyboard driver work, right now I am suffering. --- linker.ld | 4 ++ makefile | 5 +- src/headers/graphics.h | 2 +- src/headers/keyboard.h | 27 ++++------ src/headers/memMap.h | 16 ++++++ src/headers/paging.h | 2 + src/headers/scheduler.h | 1 + src/headers/stddef.h | 19 +++++-- src/headers/stdlib.h | 5 ++ src/headers/tty.h | 19 +++++-- src/kernel/entry.c | 64 +++++++++++++++++++---- src/kernel/graphics.c | 53 +++++++++++++++---- src/kernel/keyboard.c | 112 ++++++++++++++++++++++++++++++++++++++++ src/kernel/memMap.c | 109 ++++++++++++++++++++++++++++++++++++++ src/kernel/scheduler.c | 12 +++++ src/kernel/stdlib.c | 55 ++++++++++++++++++++ src/kernel/tty.c | 28 ++++++++-- src/memManager/header.h | 14 +++++ src/memManager/src.c | 94 +++++++++++++++++++++++++++++++++ 19 files changed, 590 insertions(+), 51 deletions(-) create mode 100644 src/headers/memMap.h create mode 100644 src/kernel/keyboard.c create mode 100644 src/kernel/memMap.c create mode 100644 src/memManager/header.h create mode 100644 src/memManager/src.c diff --git a/linker.ld b/linker.ld index 37b5f48..52e68dc 100644 --- a/linker.ld +++ b/linker.ld @@ -6,6 +6,8 @@ KERNEL_PHYS_BASE = 0x00100000; SECTIONS { . = KERNEL_VIRT_BASE; + kernel_start = .; + .text : AT(KERNEL_PHYS_BASE) { *(.text) } @@ -22,4 +24,6 @@ SECTIONS { *(COMMON) *(.bss) } + + kernel_end = .; } \ No newline at end of file diff --git a/makefile b/makefile index 5110aa1..6d5f43b 100644 --- a/makefile +++ b/makefile @@ -9,11 +9,14 @@ build: prepare copygrub gcc -c src/kernel/tty.c -o build/tty.o -ffreestanding -O2 -Wall -Wextra -m32 # tty gcc -c src/kernel/interrupts.c -o build/interrupts.o -ffreestanding -O2 -Wall -Wextra -m32 # interrupts, C side gcc -c src/kernel/scheduler.c -o build/scheduler.o -ffreestanding -O2 -Wall -Wextra -m32 # scheduler + gcc -c src/kernel/memMap.c -o build/memMap.o -ffreestanding -O2 -Wall -Wextra -m32 # memory map + gcc -c src/memManager/src.c -o build/memManager.o -ffreestanding -O2 -Wall -Wextra -m32 # memory manager + gcc -c src/kernel/keyboard.c -o build/keyboard.o -ffreestanding -O2 -Wall -Wextra -m32 # keyboard driver gcc -c initrd/vga/main.c -o build/initrddir/vga_graph -ffreestanding -O2 -Wall -Wextra -m32 # initrd/vga driver tar -czf build/initrd build/initrddir/* # build initrd - gcc -z noexecstack -m32 -T linker.ld -o build/linked -ffreestanding -O2 -nostdlib build/scheduler.o build/interrupts.o build/intasm.o build/tty.o build/graphics.o build/boot.o build/kernel.o build/stdlib.o -fno-pie -fno-pic -no-pie # link + gcc -z noexecstack -m32 -T linker.ld -o build/linked -ffreestanding -O2 -nostdlib build/keyboard.o build/memManager.o build/memMap.o build/scheduler.o build/interrupts.o build/intasm.o build/tty.o build/graphics.o build/boot.o build/kernel.o build/stdlib.o -fno-pie -fno-pic -no-pie # link cp build/linked build/grub/boot/kernel # copy kernel over to grub template cp build/initrd build/grub/boot/JPOS.initrd # copy initrd to grub template diff --git a/src/headers/graphics.h b/src/headers/graphics.h index 3ef9131..f594abe 100644 --- a/src/headers/graphics.h +++ b/src/headers/graphics.h @@ -20,7 +20,7 @@ extern size_t VGA_rsx; extern size_t VGA_rsy; -void VGA_setchar(virtualConsole* con, uint8_t x, uint8_t y, char val); +void VGA_setchar(virtualConsole* con, uint8_t x, uint8_t y, char val, VGA_pixel color); void VGA_renderchar(virtualConsole* con); void _VGA_renchar(uint8_t x, uint8_t y, char val, uint8_t fcolor[3], uint8_t bcolor[3]); void VGA_switch(uint8_t *regs); diff --git a/src/headers/keyboard.h b/src/headers/keyboard.h index c0f997d..2b3b00f 100644 --- a/src/headers/keyboard.h +++ b/src/headers/keyboard.h @@ -1,21 +1,14 @@ #include "stddef.h" #include "stdlib.h" +#include "scheduler.h" -#define KEYBOARD_cmd_setled 0xED -#define KEYBOARD_cmd_echo 0xEE -#define KEYBOARD_cmd_setscanset 0xF0 -#define KEYBOARD_cmd_enable 0xF4 -#define KEYBOARD_cmd_disable 0xF5 -#define KEYBOARD_cmd_reset 0xFF -#define KEYBOARD_resp_ACK 0xFA -#define KEYBOARD_resp_resend 0xFE -#define KEYBOARD_resp_err 0x00 -#define KEYBOARD_resp_selftestpass 0xAA -#define KEYBOARD_resp_echo 0xEE -#define KEYBOARD_resp_testfail1 0xFC -#define KEYBOARD_resp_testfail2 0xFD -#define KEYBOARD_resp_err2 0xFF -#define KEYBOARD_cqsize 128 +#define KBD_DATA 0x60 +#define KBD_STATUS 0x64 +#define KBD_ACK 0xFA +#define KBD_RESEND 0xFE +#define BUF_SIZE 256 -extern uint8_t KEYBOARD_cmdqueue[KEYBOARD_cqsize]; -extern size_t KEYBOARD_cmdqueuesize; +void keyboard_init(); +void keyboard_irq_handler(); +void keyboard_process(); +void keyboard_loop(); \ No newline at end of file diff --git a/src/headers/memMap.h b/src/headers/memMap.h new file mode 100644 index 0000000..9c8dd01 --- /dev/null +++ b/src/headers/memMap.h @@ -0,0 +1,16 @@ +#pragma once +#include "stddef.h" +#include "stdlib.h" +#include "multiboot2.h" + +#define PAGE_SIZE 4096 +#define MAX_PAGES 1048576 // 4 GB + +extern uint8_t page_bitmap[MAX_PAGES / 8]; +extern size_t page_bitmap_memsize; +extern uint8_t page_usebitmap[MAX_PAGES / 8]; + +void process_mmap(struct multiboot_tag_mmap* mmap_tag); +void* allocPages(size_t amount, uint8_t* success); +void freePages(void* addr, size_t amount); +void reservepages(void* addr, size_t length); \ No newline at end of file diff --git a/src/headers/paging.h b/src/headers/paging.h index 66a1989..92253b8 100644 --- a/src/headers/paging.h +++ b/src/headers/paging.h @@ -6,4 +6,6 @@ typedef PAG_PT_entry_t PAG_PT_t[1024]; typedef PAG_PT_t PAG_PD_t[1024]; extern PAG_PD_t PAG_mainPD; +extern PAG_PT_t PAG_identityPT; +extern PAG_PT_t PAG_kernelPT; diff --git a/src/headers/scheduler.h b/src/headers/scheduler.h index a88864e..21d37de 100644 --- a/src/headers/scheduler.h +++ b/src/headers/scheduler.h @@ -1,3 +1,4 @@ +#pragma once #include "stddef.h" #include "stdlib.h" diff --git a/src/headers/stddef.h b/src/headers/stddef.h index 0961e17..538c8ae 100644 --- a/src/headers/stddef.h +++ b/src/headers/stddef.h @@ -1,11 +1,20 @@ #define uint8_t unsigned char #define uint16_t unsigned short -#define uint32_t unsigned int -//#define uint64_t unsigned long +#define uint32_t unsigned long +#define uint64_t unsigned long long #define int8_t signed char #define int16_t signed short -#define int32_t signed int -#//define int64_t signed long +#define int32_t signed long +#define int64_t signed long long -#define size_t uint32_t +#define size_t uint64_t + +extern uint32_t kernel_start; +extern uint32_t kernel_end; +#define HC_kernel_start ((uint32_t)&kernel_start-0xC0000000) +#define HC_kernel_end ((uint32_t)&kernel_end-0xC0000000) + +#define OK "&gOK\n" +#define YES "&gYES\n" +#define NO "&rNO\n" \ No newline at end of file diff --git a/src/headers/stdlib.h b/src/headers/stdlib.h index 0817088..53fb9d6 100644 --- a/src/headers/stdlib.h +++ b/src/headers/stdlib.h @@ -1,12 +1,17 @@ #pragma once #include "stddef.h" +void uiprint64(uint64_t x, void* func); uint32_t strlen32(char* str); +uint64_t strlen64(char* str); void strrev32(char* str); +void strrev64(char* str); uint8_t uitoa32(uint32_t x, char* str); +uint8_t uitoa64(uint64_t x, char* str); void strcon(char* x, char* y); void memcopy(void* dest, void* src, size_t size); void memset(void* dest, size_t size, uint8_t value); +void memmove(void* dest, void* src, size_t size); __attribute__((noreturn)) void kpanic(char* msg); static inline void outb(uint16_t port, uint8_t val) { diff --git a/src/headers/tty.h b/src/headers/tty.h index 126c766..2628e43 100644 --- a/src/headers/tty.h +++ b/src/headers/tty.h @@ -4,13 +4,22 @@ #define CON_sizex 40 #define CON_sizey 25 +static size_t colorSize = 5; +static char colorcodes[5] = {'w', 'r', 'g', 'b', 'N'}; + +typedef struct { + char x; + uint8_t color[3]; +} colorChar; + typedef struct { void* FU_kupdbuf; - char kstdout[8192]; + char kstdout[CON_sizex*CON_sizey]; uint16_t kstdout_count; + uint16_t kstdout_offset; uint8_t FU_forecolor[3]; uint8_t FU_backcolor[3]; - char charbuf[CON_sizex][CON_sizey]; + colorChar charbuf[CON_sizex][CON_sizey]; uint8_t enableRendering; uint16_t keyBuf[1024]; @@ -27,4 +36,8 @@ void con_kputstr(virtualConsole* con, char* x); void con_init(virtualConsole* con); void kputchar(char x); void kputstr(char* x); -void con_render(); \ No newline at end of file +void con_render(); +void con_putkey(virtualConsole* con, uint16_t key); +uint16_t con_popkey(virtualConsole* con); +uint8_t con_iskeyavail(virtualConsole* con); +uint16_t con_gettopkey(virtualConsole* con); \ No newline at end of file diff --git a/src/kernel/entry.c b/src/kernel/entry.c index c472f36..293ea1f 100644 --- a/src/kernel/entry.c +++ b/src/kernel/entry.c @@ -5,6 +5,9 @@ #include "../headers/tty.h" #include "../headers/interrupts.h" #include "../headers/scheduler.h" +#include "../headers/memMap.h" +#include "../headers/keyboard.h" +#include "../memManager/header.h" struct multiboot_info { uint32_t total_size; @@ -24,18 +27,25 @@ uint32_t findtag(uint32_t type, struct multiboot_info* info) { return 0; // failsafe } +void printok() { + kputstr(OK); + schedule_task_fl(1, &printok); +} void kernel_main(struct multiboot_info* header, uint32_t magic) { // init all consoles for (uint8_t i=0;i> 8) & 0xFF); + uint8_t high = (uint8_t)((divisor >> 8) & 0xFF); outb(0x43, 0x36); outb(0x40, low); outb(0x40, high); - kputstr("OK\n"); + kputstr(OK); IRQ_registerhandler(0x00, &tick); - while (1) {} + kputstr("Kernel size: "); + uiprint64(HC_kernel_end-HC_kernel_start, kputstr); + kputstr("\n"); + kputstr("Kernel start: "); + uiprint64(HC_kernel_start, kputstr); + kputstr("\n"); + kputstr("Kernel end: "); + uiprint64(HC_kernel_end, kputstr); + kputstr("\n"); + + struct multiboot_tag_mmap* mmap = (struct multiboot_tag_mmap*)&header->tags[findtag(MULTIBOOT_TAG_TYPE_MMAP, header)]; + process_mmap(mmap); + kputstr("Available pages: "); + uiprint64(page_bitmap_memsize, kputstr); + kputstr("\n"); + kputstr("Available memory: "); + uiprint64(page_bitmap_memsize*PAGE_SIZE, kputstr); + kputstr(" Bytes\n"); + + kputstr("Initializing memory manager..."); + MEM_pagalloc = &allocPages; + MEM_pagfree = &freePages; + kputstr(OK); + + kputstr("Initializing Keyboard..."); + IRQ_registerhandler(0x01, &keyboard_irq_handler); + keyboard_init(); + keyboard_loop(); + kputstr(OK); + + while (1) { + if (con_iskeyavail(&consoles[currentConsole])) { + kputchar(con_popkey(&consoles[currentConsole])); + } + } } \ No newline at end of file diff --git a/src/kernel/graphics.c b/src/kernel/graphics.c index 413f545..cdf5b43 100644 --- a/src/kernel/graphics.c +++ b/src/kernel/graphics.c @@ -206,7 +206,7 @@ void _VGA_renchar(uint8_t x, uint8_t y, char val, uint8_t fcolor[3], uint8_t bco void VGA_renderchar(virtualConsole* con) { for (size_t x=0;xcharbuf[x][y], con->FU_forecolor, con->FU_backcolor); + _VGA_renchar(x, y, con->charbuf[x][y].x, con->charbuf[x][y].color, con->FU_backcolor); } } } @@ -295,22 +295,32 @@ void VGA_setpal(uint8_t palette[256][3]) { VGA_setpix(i,0,(VGA_pixel){0x00,0xFF,0x00}); } } -void VGA_setchar(virtualConsole* con, uint8_t x, uint8_t y, char val) { - con->charbuf[x][y] = val; +void VGA_setchar(virtualConsole* con, uint8_t x, uint8_t y, char val, VGA_pixel color) { + con->charbuf[x][y] = (colorChar){val, {color.r, color.g, color.b}}; +} +uint8_t beginswith(char* x, char* y) { + for (size_t i=0;iFU_backcolor); size_t count = con->kstdout_count; char* buf = con->kstdout; - while (count > (CON_sizex*CON_sizey)) { - count -= (CON_sizex*CON_sizey); - buf += (CON_sizex*CON_sizey); - } - uint16_t x = 0; uint16_t y = 0; + VGA_pixel ccolor = *(VGA_pixel*)con->FU_forecolor; for (uint16_t i=0;i= CON_sizey) { + for (size_t cy=1;cycharbuf[cx][cy-1] = con->charbuf[cx][cy]; + } + } + y --; + } if (x >= CON_sizex) { x = 0; y ++; @@ -318,12 +328,35 @@ void VGA_kstrrend(virtualConsole* con) { char val = buf[i]; if (val == '\n') { + ccolor = (VGA_pixel){con->FU_forecolor[0], con->FU_forecolor[1], con->FU_forecolor[2]}; x = 0; y ++; continue; } + if (val == '&') { + VGA_pixel colors[5] = { + {0xFF, 0xFF, 0xFF}, + {0xFF, 0x00, 0x00}, + {0x00, 0xFF, 0x00}, + {0x00, 0x00, 0xFF}, + *(VGA_pixel*)con->FU_forecolor, + }; + + uint8_t found = 0; + for (size_t f=0;fsize;entry_ptr += mmap_tag->entry_size) { + struct multiboot_mmap_entry* entry = (struct multiboot_mmap_entry*)entry_ptr; + + uint64_t start = entry->addr; + uint64_t end = entry->addr + entry->len; + + // align to page boundaries + uint64_t p_start = align_up(start); + uint64_t p_end = align_down(end); + + for (uint64_t addr = p_start; addr < p_end; addr += PAGE_SIZE) { + if (entry->type == 1) { // usable, needs to be remapped + mark_page_free(addr); + } else { // no touchy touchy + mark_page_reserved(addr); + } + page_bitmap_memsize ++; + } + } + for (uint32_t addr = HC_kernel_start;addr < HC_kernel_end;addr += PAGE_SIZE) { // areas with the kernel should be kept free + mark_page_reserved(addr); + } +} +void* allocPages(size_t amount, uint8_t* success) { + if (amount == 0) {return 0;} + size_t a = 0; + size_t ind = 0; + for (size_t i=0;i 0) { str[i++] = x%10+'0'; @@ -24,6 +43,22 @@ uint8_t uitoa32(uint32_t x, char* str) { strrev32(str); return i; } +uint8_t uitoa64(uint64_t x, char* str) { + if (x == 0) { + str[0] = '0'; + str[1] = 0; + return 1; + } + + uint8_t i=0; + while (x > 0) { + str[i++] = x%10+'0'; + x /= 10; + } + str[i] = 0; + strrev64(str); + return i; +} void memcopy(void* dest, void* src, size_t size) { for (size_t i=0;ikstdout_count == 8192) { - for (uint32_t i=0;i<8191;i++) { - con->kstdout[i] = con->kstdout[i+1]; - } + while ((con->kstdout_count) > (CON_sizex*CON_sizey)) { con->kstdout_count --; + memcopy(con->kstdout, con->kstdout+1, con->kstdout_count); } con->kstdout[con->kstdout_count++] = x; if (newrender && &consoles[currentConsole] == con && con->enableRendering) { @@ -50,4 +48,26 @@ void con_render() { } else { kpanic("virtualConsole failure:\nFU_kupdbuf is 0x00."); } +} +void con_putkey(virtualConsole* con, uint16_t key) { + if (con->keyBufSize < 1024) { + con->keyBuf[con->keyBufSize++] = key; + } +} +uint16_t con_popkey(virtualConsole* con) { + if (con->keyBufSize == 0) { + return 0x0000; + } + uint16_t out = con->keyBuf[0]; + memmove(&con->keyBuf[0], &con->keyBuf[1], 1023); + return out; +} +uint8_t con_iskeyavail(virtualConsole* con) { + return con->keyBufSize > 0; +} +uint16_t con_gettopkey(virtualConsole* con) { + if (con->keyBufSize == 0) { + return 0x0000; + } + return con->keyBuf[0]; } \ No newline at end of file diff --git a/src/memManager/header.h b/src/memManager/header.h new file mode 100644 index 0000000..7534284 --- /dev/null +++ b/src/memManager/header.h @@ -0,0 +1,14 @@ +#include "../headers/stddef.h" +#include "../headers/memMap.h" + +extern void* MEM_pagalloc; +extern void* MEM_pagfree; + +typedef struct { + void* prev; + size_t size; + void* next; +} MEM_tag; + +extern void* malloc(size_t); +extern void free(void*); \ No newline at end of file diff --git a/src/memManager/src.c b/src/memManager/src.c new file mode 100644 index 0000000..68dc3ef --- /dev/null +++ b/src/memManager/src.c @@ -0,0 +1,94 @@ +#include "header.h" + +void* MEM_pagalloc = 0x00; +void* MEM_pagfree = 0x00; + +uint8_t pagealloc(MEM_tag** addr, size_t amount) { + if (MEM_pagalloc != 0x00) { + uint8_t suc; + void* ptr = ((void* (*)(size_t, uint8_t*))MEM_pagalloc)(amount, &suc); + if (!suc) {return 1;} + *addr = ptr; + return 0; + } + return 1; +} +void pagefree(void* addr, size_t amount) { + if (MEM_pagfree != 0x00) { + ((void (*)(void*, size_t))MEM_pagfree)(addr, amount); + } +} +inline size_t getTotalBytesAmount(size_t bytes) { + return bytes+sizeof(MEM_tag); +} +inline size_t getTotalPagesAmount(size_t bytes) { + return getTotalBytesAmount(bytes)/PAGE_SIZE + (getTotalBytesAmount(bytes)%PAGE_SIZE > 0 ? 1 : 0); +} + +MEM_tag* memprim = 0x00; + +// does this remind you of a linked list, ya? +void* malloc(size_t bytes) { + if (memprim == 0x00) { // we have to allocate the primary memory thing first. + if (pagealloc(&memprim, getTotalPagesAmount(bytes))) { + return (void*)0x00; + } + memprim->size = getTotalBytesAmount(bytes); + memprim->next = 0x00; + memprim->prev = 0x00; + return (void*)((size_t)memprim+sizeof(MEM_tag)); + } + + // if we are here, we find the "topmost" memory tag first. + MEM_tag* topmost = memprim; + while (1) { // simple as that. + if (topmost->next == 0x00) { + break; + } else { + topmost = topmost->next; + } + } + + MEM_tag* newtag; + if (pagealloc(&newtag, getTotalPagesAmount(bytes))) { + return (void*)0x00; + } + newtag->prev = topmost; + newtag->next = 0x00; + topmost->next = newtag; + newtag->size = getTotalBytesAmount(bytes); + return (void*)((size_t)newtag+sizeof(MEM_tag)); +} +void free(void* address) { + if (memprim == 0x00) {return;} + // find the tag associated with the address. + MEM_tag* tag = memprim; + while (1) { + if ((size_t)tag+sizeof(MEM_tag) == address) { // this is the tag. + if (tag->next != 0x00) { + if (tag->prev != 0x00) { + ((MEM_tag*)tag->next)->prev = tag->prev; + } else { + ((MEM_tag*)tag->next)->prev = 0x00; + memprim = tag->next; + } + } + if (tag->prev != 0x00) { + if (tag->next != 0x00) { + ((MEM_tag*)tag->prev)->next = tag->next; + } else { + ((MEM_tag*)tag->prev)->next = 0x00; + } + } else { // since prev is 0x00 we must be memprim (except something messed with our tag.) + memprim = 0x00; + } + pagefree(tag, getTotalPagesAmount(tag->size-sizeof(MEM_tag))); + return; + } + if (tag->next != 0x00) { + tag = tag->next; + } else { + return; + } + } +} \ No newline at end of file