From 90eb69f424c03432a404b5074110498066db4b0a Mon Sep 17 00:00:00 2001 From: notsomeidiot123 Date: Wed, 30 Oct 2024 11:16:25 -0400 Subject: [PATCH] CPU IO ports, and basic serial driver --- .vscode/settings.json | 5 +++ makefile | 11 ++++-- src/bootloader/main.s | 1 + src/kernel/arch_i386/interrupts.c | 5 +++ src/kernel/arch_i386/memory.c | 20 ++++++++++ src/kernel/drivers/cpuio.h | 22 +++++++++++ src/kernel/drivers/serial.c | 65 +++++++++++++++++++++++++++++++ src/kernel/drivers/serial.h | 9 +++++ src/kernel/kmain.c | 9 ++++- src/kernel/shared/interrupts.h | 1 + src/kernel/shared/kstdlib.h | 12 ++++++ src/kernel/shared/memory.h | 64 ++++++++++++++++++++++++++++++ src/kernel/shared/string.h | 14 +++++++ src/kernel/system/string.c | 52 +++++++++++++++++++++++++ 14 files changed, 284 insertions(+), 6 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 src/kernel/arch_i386/interrupts.c create mode 100644 src/kernel/arch_i386/memory.c create mode 100644 src/kernel/drivers/cpuio.h create mode 100644 src/kernel/drivers/serial.c create mode 100644 src/kernel/drivers/serial.h create mode 100644 src/kernel/shared/interrupts.h create mode 100644 src/kernel/shared/kstdlib.h create mode 100644 src/kernel/shared/memory.h create mode 100644 src/kernel/shared/string.h create mode 100644 src/kernel/system/string.c diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..ab5f439 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "serial.h": "c" + } +} \ No newline at end of file diff --git a/makefile b/makefile index 9e67912..33c3ea2 100644 --- a/makefile +++ b/makefile @@ -2,7 +2,7 @@ CC := gcc AS := nasm CFLAGS = -c -mno-sse -mno-sse2 -mno-red-zone -ffreestanding -m32 -nostdlib -O3 -fno-pie -fno-stack-protector -mno-mmx BL_ASFLAGS := -f bin -SRCS := $(wildcard src/kernel/*.c) +SRCS := $(wildcard src/kernel/*/*.c) OBJS := $(patsubst src/kernel/%.c, bin/kernel/%.o, $(SRCS)) all: bootloader tools kernel @@ -16,12 +16,15 @@ tools: bootloader: $(AS) src/bootloader/main.s $(BL_ASFLAGS) -o bin/bootloader.bin -kernel: $(OBJS) +# kernel: $(OBJS) +kernel: nasm src/kernel/entry.s -o bin/kernel/entry.o -f elf32 + sh c_build_helper.sh # ld -T linker.ld bin/kernel/entry.o bin/kernel/*.o -melf_i386 ld -T linker.ld bin/kernel/*.o -melf_i386 -%.o: $(SRCS) - $(CC) $(CFLAGS) $< -o $@ +# %.o: $(SRCS) +# mkdir -p bin/kernel/$(shell dirname $@) +# $(CC) $(CFLAGS) $< -o $@ init: @mkdir mount diff --git a/src/bootloader/main.s b/src/bootloader/main.s index 3ac30c2..10c46f9 100644 --- a/src/bootloader/main.s +++ b/src/bootloader/main.s @@ -779,6 +779,7 @@ k_info: .yres: dw 25 .framebuffer_ptr: dd 0xb8000 .loaded_modules: dd 0 + .loaded_module_c: dd 0 ;loaded_modules points to a struct array containing a ptr to the entry point of each pre-loaded module to be executed during startup ;module_struct: ;.entry_point: dd 0 diff --git a/src/kernel/arch_i386/interrupts.c b/src/kernel/arch_i386/interrupts.c new file mode 100644 index 0000000..0434c72 --- /dev/null +++ b/src/kernel/arch_i386/interrupts.c @@ -0,0 +1,5 @@ +#include "../shared/interrupts.h" + +void init_idt(){ + +} \ No newline at end of file diff --git a/src/kernel/arch_i386/memory.c b/src/kernel/arch_i386/memory.c new file mode 100644 index 0000000..4a89f8b --- /dev/null +++ b/src/kernel/arch_i386/memory.c @@ -0,0 +1,20 @@ +#include +#include "../shared/memory.h" +#include "../shared/kstdlib.h" +uint8_t pm_map[0x20000]; + +int pm_alloc(){ + +} +int pm_init(kernel_info_t *kernel_info){ + +} +void map(void *vaddr, void *paddr, uint32_t flags){ + uint32_t pd_index = (uint32_t)vaddr >> 22; + uint32_t pt_index = (uint32_t)vaddr >> 12 & 0x3ff; + + uint32_t *pd = (uint32_t*)0xfffff000; + if(!pd[pd_index]){ + pd[pd_index] = pm_alloc(); + } +} diff --git a/src/kernel/drivers/cpuio.h b/src/kernel/drivers/cpuio.h new file mode 100644 index 0000000..7e02313 --- /dev/null +++ b/src/kernel/drivers/cpuio.h @@ -0,0 +1,22 @@ +#pragma once +#include + +inline void outb(uint16_t port, uint8_t data){ + asm volatile ("outb %0, %1" :: "a"(data), "Nd"(port)); +} + +inline void outw(uint16_t port, uint16_t data){ + asm volatile ("outw %0, %1" :: "a"(data), "Nd"(port)); +} + +inline uint8_t inb(uint16_t port){ + uint8_t byte = 0; + asm volatile ("inb %1, %0" : "=a"(byte) : "Nd"(port)); + return byte; +} + +inline uint16_t inw(uint16_t port){ + uint16_t word = 0; + asm volatile ("inw %1, %0" : "=a"(word) : "Nd"(port)); + return word; +} \ No newline at end of file diff --git a/src/kernel/drivers/serial.c b/src/kernel/drivers/serial.c new file mode 100644 index 0000000..c67ff1b --- /dev/null +++ b/src/kernel/drivers/serial.c @@ -0,0 +1,65 @@ +#include "serial.h" +#include "../shared/memory.h" +#include "../shared/string.h" +#include "cpuio.h" +#include +#include +// #include + +uint16_t com_ports[8]; +uint8_t com_buffer[8][128]; +uint8_t com_buffer_index[8] = {0}; + +void init_serial(){ + bda_t *bda = (void*)0x400; + for(int i = 0; i < 4; i++){ + com_ports[i] = bda->com_ports[i]; + } +} +void serial_writeb(uint8_t port, uint8_t data){ + if(com_ports[port] == 0){ + com_buffer[port][com_buffer_index[port]++] = data; + } + outb(com_ports[port], data); +} +uint8_t serial_readb(uint8_t port){ + if(com_ports[port] == 0){ + return com_buffer[port][com_buffer_index[port]--]; + } + return inb(com_ports[port]); +} +void serial_writereg(uint8_t port, uint8_t reg, uint8_t data){ + if(com_ports[port] == 0 || reg > 8) return; + outb(com_ports[port] + reg, data); +} +uint8_t serial_readreg(uint8_t port, uint8_t reg){ + if(com_ports[port] == 0 || reg > 8) return -1; + return inb(com_ports[port] + reg); +} + +void debug_puts(char *string){ + while(*string){ + // serial_writeb(0, *(string++)); + outb(com_ports[0], *string++); + } +} + +void printf(char *string, ...){ + va_list vars; + va_start(vars, string); + while(*string){ + if(*string == '%'){ + switch(*(string + 1)){ + case 'd': + string += 2; + int32_t num = va_arg(vars, int32_t); + char numb[12]; + itoa(num, numb, 10); + debug_puts(numb); + continue; + } + } + outb(com_ports[0], *string); + string++; + } +} \ No newline at end of file diff --git a/src/kernel/drivers/serial.h b/src/kernel/drivers/serial.h new file mode 100644 index 0000000..4a62e0c --- /dev/null +++ b/src/kernel/drivers/serial.h @@ -0,0 +1,9 @@ +#pragma once +#include +void init_serial(); +void serial_writeb(uint8_t port, uint8_t data); +void serial_writereg(uint8_t port, uint8_t reg, uint8_t data); +uint8_t serial_readreg(uint8_t port, uint8_t reg); +uint8_t serial_readb(uint8_t port); +void debug_puts(char *string); +void printf(char *string, ...); \ No newline at end of file diff --git a/src/kernel/kmain.c b/src/kernel/kmain.c index 8b07dcb..a14b68c 100644 --- a/src/kernel/kmain.c +++ b/src/kernel/kmain.c @@ -1,5 +1,10 @@ #include "shared/memory.h" -extern void kmain(){ - pm_init(); +#include "shared/string.h" +#include "shared/kstdlib.h" +#include "drivers/serial.h" + +extern void kmain(kernel_info_t *kernel_info){ + init_serial(); + pm_init(kernel_info); return; } \ No newline at end of file diff --git a/src/kernel/shared/interrupts.h b/src/kernel/shared/interrupts.h new file mode 100644 index 0000000..4b3b43b --- /dev/null +++ b/src/kernel/shared/interrupts.h @@ -0,0 +1 @@ +void init_idt(); \ No newline at end of file diff --git a/src/kernel/shared/kstdlib.h b/src/kernel/shared/kstdlib.h new file mode 100644 index 0000000..b2bb6a1 --- /dev/null +++ b/src/kernel/shared/kstdlib.h @@ -0,0 +1,12 @@ +#include "memory.h" +typedef struct kernel_info{ + memory_map_entry *mmap_ptr; + uint16_t mmap_entry_count; + uint8_t padding; + uint8_t pixel_depth; + uint16_t monitor_x_resolution; + uint16_t monitor_y_resolution; + void *framebuffer; + void *loaded_modues; + uint32_t loaded_module_count; +}__attribute__((packed)) kernel_info_t; \ No newline at end of file diff --git a/src/kernel/shared/memory.h b/src/kernel/shared/memory.h new file mode 100644 index 0000000..e1cef09 --- /dev/null +++ b/src/kernel/shared/memory.h @@ -0,0 +1,64 @@ +#pragma once +#include + +#define PD_PRESENT 0x0001 +#define PD_USER_RW 0x0002 +#define PD_USER 0x0004 +#define PD_PWT 0x0008 +#define PD_PCD 0x0010 +#define PD_ACCESSED 0x0020 +#define PD_DIRTY 0x0040 +#define PD_PAGE_SZ 0x0080 +#define PD_GLOBAL 0x0100 +#define PD_PAT 0x1000 +#define PD_LINK_N 0x0200 +#define PD_LINK_L 0x0400 +#define PD_ALLOC 0x0800 + +#define PT_PRESENT 0X0001 +#define PT_USER_RW 0x0002 +#define PT_USER 0x0004 +#define PT_PWT 0x0008 +#define PT_PCD 0x0010 +#define PT_ACCESSED 0x0020 +#define PT_DIRTY 0x0040 +#define PT_PAT 0x0080 +#define PT_GLOBAL 0x0100 +#define PT_LINK_N 0x0200 +#define PT_LINK_L 0x0400 +#define PT_ALLOC 0x0800 + +#define BIOS_MMAP_USABLE 1 +#define BIOS_MMAP_RESERVED 2 +#define BIOS_MMAP_RECLAIM 3 +#define BIOS_MMAP_NVS 4 +#define BIOS_MMAP_BAD_MEMORY 5 + +typedef struct BIOS_data{ + uint16_t com_ports[4]; + uint16_t lpt_ports[3]; + uint16_t ebda_addr; + uint16_t hw_bitflags; + uint16_t kb_to_ebda; + uint16_t kbd_state; + char kbd_buffer[32]; + uint8_t display_mode; + uint16_t columns_text; + uint16_t base_video_port; + uint16_t irq0_boot; + uint8_t hard_drives; + uint16_t kbd_buffer_start; + uint16_t kbd_buffer_end; + uint8_t kbd_led_state; +}__attribute__((packed)) bda_t; + +typedef struct memory_map_entry{ + uint64_t entry_base; + uint64_t entry_length; + uint32_t type; + uint32_t extended_bitflags; +}__attribute__((packed))mmap_entry_t; + +void map(void *vaddr, void *paddr, uint32_t flags); +void map_4mb(void *vaddr, void* paddr, uint32_t flags); +int pm_init(kernel_info_t *kernel_info); \ No newline at end of file diff --git a/src/kernel/shared/string.h b/src/kernel/shared/string.h new file mode 100644 index 0000000..a51a35f --- /dev/null +++ b/src/kernel/shared/string.h @@ -0,0 +1,14 @@ +#pragma once +#include + +void itoa(int64_t data, char *res, uint8_t base); +void strpad(char *string, char padding, uint32_t length); +inline uint32_t strlen(char *str){ + uint32_t c = 0; + while(*str){ + str++; + c++; + } + return c; +} +void strcpy(char *src, char *dest); \ No newline at end of file diff --git a/src/kernel/system/string.c b/src/kernel/system/string.c new file mode 100644 index 0000000..22d64f7 --- /dev/null +++ b/src/kernel/system/string.c @@ -0,0 +1,52 @@ +#include +#include "../shared/string.h" +//res needs to allocate enough space for 12 chars minimum +void itoa(int64_t data, char *res, uint8_t base){ + char carr[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + char negative = 0; + if(res == 0) return; + if(data < 0 && base == 10){ + data *= -1; + negative = 1; + } + int ptr = 0; + char buffer[12] = {0}; + // res[11] = 0; + if(data == 0){ + res[0] = '0'; + res[1] = 0; + } + uint32_t tmp = data; + while(tmp){ + buffer[ptr++] = carr[tmp % base]; + tmp /= base; + } + uint32_t rindex = 0; + res[ptr] = 0; + while(ptr > 0){ + res[--ptr + negative] = buffer[rindex++]; + } + res[0] += negative * '-'; + return; +} + +void strcpy(char *src, char *dest){ + if(src == 0 || dest == 0){ + return; + } + uint32_t len = strlen(src); + for(int i = 0; i < len; i++){ + dest[i] = src[i]; + } + dest[len] = 0; +} + +void strpad(char *string, char padding, uint32_t length){ + if(strlen(string) >= padding) return; + char tmp[length]; + for(int i = 0; i < length - strlen(string); i++){ + tmp[i] = padding; + } + strcpy(string, tmp + length - strlen(string)); + strcpy(tmp, string); +} \ No newline at end of file