diff --git a/Documentation/Modules and drivers API.txt b/Documentation/Modules and drivers API.txt new file mode 100644 index 0000000..6b6ae80 --- /dev/null +++ b/Documentation/Modules and drivers API.txt @@ -0,0 +1,21 @@ +Modules and Drivers API + + +This file contains documentation for the Module/Driver API. + + +The kernel symtab is always at 0xC0101000, and can go up to 0xC0101000 + 0x8086 ( See what I did there?) + + +ID number -- Function -- Returns -- Arguments +0 -- get_kinfo -- kinfo_t -- uint32_t leaf +1 -- make_kfunc -- kfunc_t -- void* addr, bool module, uint16_t module_id, uint32_t function_id +2 -- add_kfunc -- uint32_t -- void* addr, bool module, uint16_t module_id, uint32_t function_id +3 -- printf -- void -- const char* format, ... +4 -- malloc -- void* -- size_t size +5 -- free -- void -- void* ptr +6 -- calloc -- void* -- size_t nmemb, size_t size +7 -- realloc -- void* -- void* ptr, size_t size +8 -- get_key -- uint16_t -- void +9 -- get_string -- char* -- void +10 -- diff --git a/Makefile b/Makefile index 736f1be..ba05820 100644 --- a/Makefile +++ b/Makefile @@ -9,12 +9,15 @@ MKFS_VFAT := sudo mkfs.vfat MKFS_FLAGS := -F 32 -S 512 NASMFLAGS := -f elf32 WNOFLAGS := -Wno-discarded-qualifiers -CFLAGS := -std=gnu99 -ffreestanding -O2 -Wall -Wextra -msse $(WNOFLAGS) +CFLAGS := -std=gnu99 -ffreestanding -O2 -Wall -Wextra -msse4 $(WNOFLAGS) LDFLAGS := -T linker.ld -ffreestanding -O2 -nostdlib QEMUFLAGS := -boot d -cdrom $(ISO) -drive file=espresso.img,format=raw,if=ide,readonly=off,rerror=report,werror=report -cpu qemu32,sse4.1 -QEMUFLGS_EXT := -net none -netdev user,id=n0 -device rtl8139,netdev=n0 #-singlestep +QEMUFLGS_EXT := -net none -netdev user,id=n0 -device rtl8139,netdev=n0 -vga std #-singlestep SRC_DIRS := kernel drivers lib INCLUDE_DIRS := include +ARCH_DIR := arch +X86_ARCH_DIR := $(ARCH_DIR)/x86 +X86_BOOT_DIR := $(X86_ARCH_DIR)/boot INCLUDES := $(addprefix -I, $(INCLUDE_DIRS)) ISO_DIR := isodir BOOT_DIR := $(ISO_DIR)/boot @@ -23,8 +26,8 @@ GRUB_CFG := grub.cfg # === File collection === C_SRCS := $(foreach dir, $(SRC_DIRS), $(shell find $(dir) -name '*.c')) -S_SRCS := boot.s crti.s crtn.s misc_asm.s -NASM_SRCS := gdt.asm pit.asm isr.asm +S_SRCS := $(foreach dir, $(ARCH_DIR), $(shell find $(dir) -name '*.s')) +NASM_SRCS := $(foreach dir, $(ARCH_DIR), $(shell find $(dir) -name '*.asm')) CRTI_OBJ := crti.o CRTBEGIN_OBJ := $(shell $(CC) $(CFLAGS) -print-file-name=crtbegin.o) CRTEND_OBJ := $(shell $(CC) $(CFLAGS) -print-file-name=crtend.o) @@ -37,11 +40,17 @@ INTERNAL_OBJS := $(CRTI_OBJ) $(OBJS) $(CRTN_OBJ) # === Build all targets === build: all iso run +# === Build all targets and clean === +buildc: test all iso run clean + # === Default target === all: $(TARGET) +test: + printf $(CRTI_OBJ) + # === Linking === -$(TARGET): boot.o $(filter-out boot.o, $(OBJ_LINK_LIST)) +$(TARGET): ./arch/x86/boot/boot.o $(filter-out boot.o, $(OBJ_LINK_LIST)) @mkdir -p $(dir $@) $(CC) $(LDFLAGS) -o $@ $^ -lgcc diff --git a/boot.s b/arch/x86/boot/boot.s similarity index 100% rename from boot.s rename to arch/x86/boot/boot.s diff --git a/gdt.asm b/arch/x86/gdt.asm similarity index 100% rename from gdt.asm rename to arch/x86/gdt.asm diff --git a/isr.asm b/arch/x86/isr.asm similarity index 100% rename from isr.asm rename to arch/x86/isr.asm diff --git a/misc_asm.s b/arch/x86/misc_asm.s similarity index 100% rename from misc_asm.s rename to arch/x86/misc_asm.s diff --git a/pit.asm b/arch/x86/pit.asm similarity index 100% rename from pit.asm rename to arch/x86/pit.asm diff --git a/arch/x86/vga_fonts.asm b/arch/x86/vga_fonts.asm new file mode 100644 index 0000000..f518afc --- /dev/null +++ b/arch/x86/vga_fonts.asm @@ -0,0 +1,86 @@ + +global _get_fonts_asm + +_get_fonts_asm: + +; NOTE: this code is taken from https://wiki.osdev.org/VGA_Fonts + + ;in: edi=4k buffer + ;out: buffer filled with font + ;clear even/odd mode + mov dx, 03ceh + mov ax, 5 + out dx, ax + ;map VGA memory to 0A0000h + mov ax, 0406h + out dx, ax + ;set bitplane 2 + mov dx, 03c4h + mov ax, 0402h + out dx, ax + ;clear even/odd mode (the other way, don't ask why) + mov ax, 0604h + out dx, ax + ;copy charmap + mov esi, 0A0000h + mov ecx, 256 + ;copy 16 bytes to bitmap +@@: movsd + movsd + movsd + movsd + ;skip another 16 bytes + add esi, 16 + loop @@ + ;restore VGA state to normal operation + mov ax, 0302h + out dx, ax + mov ax, 0204h + out dx, ax + mov dx, 03ceh + mov ax, 1005h + out dx, ax + mov ax, 0E06h + out dx, ax + + +_set_fonts_asm: +; NOTE: this code is taken from https://wiki.osdev.org/VGA_Fonts and edited a little bit + + ;in: esi=4k buffer + ;out: buffer filled with font + ;clear even/odd mode + mov dx, 03ceh + mov ax, 5 + out dx, ax + ;map VGA memory to 0A0000h + mov ax, 0406h + out dx, ax + ;set bitplane 2 + mov dx, 03c4h + mov ax, 0402h + out dx, ax + ;clear even/odd mode (the other way, don't ask why) + mov ax, 0604h + out dx, ax + ;copy charmap + mov edi, 0A0000h + mov ecx, 256 + ;copy 16 bytes to bitmap +m: movsd + movsd + movsd + movsd + ;skip another 16 bytes + add esi, 16 + loop m + ;restore VGA state to normal operation + mov ax, 0302h + out dx, ax + mov ax, 0204h + out dx, ax + mov dx, 03ceh + mov ax, 1005h + out dx, ax + mov ax, 0E06h + out dx, ax diff --git a/drivers/irq.c b/drivers/irq.c index 35d98ec..ad0e83c 100644 --- a/drivers/irq.c +++ b/drivers/irq.c @@ -9,6 +9,8 @@ irq_func_t func_list[NUM_IRQS]; irq_func_t aux_func_list[NUM_IRQS]; + + static volatile uint32_t num_irqs_missed = 0; void irq_init(void) diff --git a/drivers/ps2_keyboard.c b/drivers/ps2_keyboard.c index ab52a2c..4ffeb7e 100644 --- a/drivers/ps2_keyboard.c +++ b/drivers/ps2_keyboard.c @@ -2,6 +2,7 @@ #include #include #include +#include #include diff --git a/include/ksymtab.h b/include/ksymtab.h index 3d26835..8c92be8 100644 --- a/include/ksymtab.h +++ b/include/ksymtab.h @@ -3,4 +3,21 @@ #include +typedef struct kfunc { + /* + Bit 31 = 1 -> driver/module function, Bit 31 = 0 -> kernel function + Bits 30-20 -> module/driver ID (11 bits) + Bits 19-0 -> function ID (20 bits) + */ + uint32_t id; + + uint32_t addr; /* Pointer to function, 0x0 if nonexistent */ +} kfunc_t; + +uint64_t kfunc_call(kfunc_t* func, uint32_t a, uint32_t b, uint32_t c, uint32_t d); +uint64_t call_kfunc_by_id(uint32_t id, uint32_t a, uint32_t b, uint32_t c, uint32_t d); + +uint32_t add_kfunc(void* addr, bool module, uint16_t module_id, uint32_t function_id); +kfunc_t make_kfunc(void* addr, bool module, uint16_t module_id, uint32_t function_id); + #endif diff --git a/kernel/kernel.c b/kernel/kernel.c index d2ad74e..d0a76b0 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -51,7 +51,7 @@ void kernel_main(multiboot_info_t* mbd, uint32_t magic) /* --- BEGIN INITIALIZATION SECTION --- */ - const char* espresso_kernel_version = "0.0.1d"; + const char* espresso_kernel_version = "0.0.1e"; /* We need to initialize the terminal so that any error/debugging messages show. */ terminal_initialize(); diff --git a/lib/ksymtab.c b/lib/ksymtab.c index 735f26e..8835391 100644 --- a/lib/ksymtab.c +++ b/lib/ksymtab.c @@ -2,20 +2,12 @@ #include -typedef struct kfunc { - /* - Bit 31 = 1 -> driver/module function, Bit 31 = 0 -> kernel function - Bits 30-20 -> module/driver ID (11 bits) - Bits 19-0 -> function ID (20 bits) - */ - uint32_t id; - - uint32_t addr; /* Pointer to function, 0x0 if nonexistent */ -} kfunc_t; + #define KFUNC_TABLE_ADDRESS 0xC0101000 -#define KFUNC_TABLE_SIZE (2 ^ 31) /* Maybe? who knows? */ + +#define KSYMTAB_MAX 0x8086FF #define IS_MODULE_FUNC(id) ((id) & 0x80000000) #define GET_MODULE_ID(id) (((id) >> 20) & 0x7FF) @@ -26,9 +18,10 @@ typedef struct kfunc { #define MAKE_MODULE_FUNC(mid, fid) (0x80000000 | ((mid) << 20) | ((fid) & 0xFFFFF)) - kfunc_t* kfunc_table = (kfunc_t*)KFUNC_TABLE_ADDRESS; +static uint32_t ktab_size = 0; + uint64_t kfunc_call(kfunc_t* func, uint32_t a, uint32_t b, uint32_t c, uint32_t d) { @@ -53,7 +46,7 @@ uint64_t kfunc_call(kfunc_t* func, uint32_t a, uint32_t b, uint32_t c, uint32_t uint64_t call_kfunc_by_id(uint32_t id, uint32_t a, uint32_t b, uint32_t c, uint32_t d) { - for (int i = 0; i < KFUNC_TABLE_SIZE; i++) + for (int i = 0; i < (int)ktab_size; i++) { if (kfunc_table[i].id == id) { @@ -67,3 +60,65 @@ uint64_t call_kfunc_by_id(uint32_t id, uint32_t a, uint32_t b, uint32_t c, uint3 return -1; } + +uint32_t add_kfunc(void* addr, bool module, uint16_t module_id, uint32_t function_id) +{ + if (ktab_size >= KSYMTAB_MAX) + { + return 0xFFFFFFFF; + } + + kfunc_t kf = make_kfunc(addr, module, module_id, function_id); + kfunc_table[ktab_size] = kf; + + ktab_size++; + + return kf.id; +} + +/* + Constructs and returns a kfunc_t: + - 'addr' is the address of the function (can be NULL/0) + - 'module' indicates if it's a module/driver function + - 'module_id' is used only if 'module' is true (11 bits max) + - 'function_id': + - 20 bits if module is true + - 31 bits if kernel function +*/ +kfunc_t make_kfunc(void* addr, bool module, uint16_t module_id, uint32_t function_id) +{ + uint32_t id; + + if (module) + { + id = 0x80000000 | ((module_id & 0x7FF) << 20) | (function_id & 0xFFFFF); + } + else + { + if (function_id == UINT32_MAX) + { + function_id = ktab_size; + } + id = function_id & 0x7FFFFFFF; + } + + kfunc_t result = { + .id = id, + .addr = (uint32_t)(uintptr_t)addr + }; + + return result; +} + +kfunc_t* find_kfunc(uint32_t id) +{ + for (uint32_t i = 0; i < ktab_size; i++) + { + if (kfunc_table[i].id == id) + { + return &kfunc_table[i]; + } + } + return NULL; +} + diff --git a/lib/mm/heap.c b/lib/mm/heap.c index e7d4705..98b21a1 100644 --- a/lib/mm/heap.c +++ b/lib/mm/heap.c @@ -134,3 +134,4 @@ void free(void* ptr) prev->next = block->next; } } + diff --git a/lib/mm/paging.c b/lib/mm/paging.c index fd84c58..6e45cf5 100644 --- a/lib/mm/paging.c +++ b/lib/mm/paging.c @@ -79,3 +79,4 @@ void map_page(void* phys_addr, void* virt_addr) asm volatile ("invlpg (%0)" :: "r" (virt_addr) : "memory"); } + diff --git a/lib/mm/pmm.c b/lib/mm/pmm.c index 637780c..840c73b 100644 --- a/lib/mm/pmm.c +++ b/lib/mm/pmm.c @@ -77,3 +77,4 @@ void free_page(void* ptr) uint32_t idx = (uint32_t)ptr / PAGE_SIZE; clear_bit(idx); } + diff --git a/lib/printf.c b/lib/printf.c index 01e9b53..0165c6b 100644 --- a/lib/printf.c +++ b/lib/printf.c @@ -26,7 +26,8 @@ void printdc(const char* str, uint8_t color) terminal_setcolor(c); } -void printf(const char* format, ...) { +void printf(const char* format, ...) +{ va_list args; va_start(args, format);