diff --git a/TODO b/TODO index 7fbb54d..9bf771a 100644 --- a/TODO +++ b/TODO @@ -1,189 +1,106 @@ -=== Todo === +TODO +==== -Legend: +Legend +------ - [ ] Not done - [x] Done - [_] Was done at some point, but isn't now - [!] Important todo - [?] Optional -- [ ] Refactoring - - [ ] Use UEFI - - [ ] Use an existing bootloader - - [x] libc - User space - - [x] libk - Kernel libc - - [x] Kernel rewrite - - [ ] Better filesystem - - [x] Makefile refactorin' (finally done!!!) +Todos +----- +- [ ] Kernel + - [ ] Syscalls + - [ ] exit() + - [ ] fork() + - [ ] read() + - [ ] write() + - [ ] open() + - [ ] close() + - [ ] waitpid() + - [ ] creat() + - [ ] link() + - [ ] unlink() + - [ ] execve() + - [ ] chdir() + - [ ] time() + - [ ] mknod() + - [ ] chmod() + - [ ] chown() + - [ ] break() + - [ ] stat() + - [ ] mount() + - [ ] umount() + - [ ] alarm() + - [ ] pause() + - [ ] access() + - [ ] nice() + - [ ] sync() + - [ ] kill() + - [ ] rename() + - [ ] mkdir() + - [ ] rmdir() + - [ ] dup() + - [ ] pipe() + - [ ] Memory + - [ ] Physical MM + - [ ] Virtual MM + - [ ] Paging + - [ ] Kernel Heap + - [ ] Drivers + - [x] tty + - [x] serial + - [ ] Timer + - [ ] VFS + - [ ] RAMFS + - [ ] FAT32 + - [ ] DevFS + - [ ] SysFS + - [ ] ProcFS -- [ ] LIBC - - [ ] assert.h - - [ ] complex.h (idk why we would need this) - - [x] ctype.h - - [x] errno.h - - [x] fcntl.h - - [x] float.h - - [x] limits.h - - [x] math.h (maybe a separate libm?) TODO: add errno errors in there - - [x] setjmp.h (this plagues my mind) - - [ ] signal.h (we would need signals first) - - [x] stdarg.h - - [x] stdbool.h - - [x] stddef.h - - [x] stdint.h - - [x] stdio.h - - [x] stdlib.h - - [x] string.h - - [x] syscall.h - - [x] time.h - - [ ] unistd.h (do we do POSIX?) - - [ ] wchar.h (we would need text support for wide chars ig?) - - [ ] wctype.h (same as above) - - [ ] sys/ - - [ ] types.h (syscall types) - - [ ] gfx.h (basic graphics lib) +- [ ] Bootloader + - [ ] MBR + - [ ] EFI -- [x] LIBK - - [x] drivers - everything that works with hardware - - [x] error - error handling (bigerr is not enough :( ) - - [x] fs - filesystem - - [x] interrupt - handling and registering interupts - - [x] memory - memory managing (physical and virtual) - - [x] screen - everything that displays on the screen - - [x] syscall - system calls +- [ ] Libc + - [ ] assert.h + - [ ] complex.h (idk why we would need this) + - [ ] ctype.h + - [ ] errno.h + - [ ] fcntl.h + - [ ] float.h + - [ ] limits.h + - [ ] math.h + - [ ] setjmp.h (this plagues my mind) + - [ ] signal.h (we would need signals first) + - [ ] stdarg.h + - [ ] stdbool.h + - [ ] stddef.h + - [ ] stdint.h + - [ ] stdio.h + - [ ] stdlib.h + - [ ] string.h + - [ ] syscall.h + - [ ] time.h + - [ ] unistd.h (does POSIX need us?) + - [ ] wchar.h (we would need text support for wide chars ig?) + - [ ] wctype.h (same as above) -- [x] Multistage Bootloader -- [x] Bootloader reads filesystem to find files -- [x] The almighty 'printf()' -- [x] Write down where stuff is in memory (in notes.txt) +- [ ] Userspace + - [ ] sh + - [ ] as + - [ ] cc + - [ ] ld + - [ ] editor + - [ ] binutils + - [ ] coreutils + - [ ] minesweeper + - [ ] solitaire + - [ ] tetris + - [ ] doom -- [ ] "Text" mode (not actually) - - [x] Scrolling - - [ ] Scroll-back - - [x] Color codes (and just multicolor text in general) - - [x] Controll sequences! - - [x] VESA BIOS Extensions - - [x] Better resolution - - [x] Graphics mode - - [x] Custom font - - [_] Larger text size - - [ ] Variable text size :) - - [x] Make output overflow go to next line - - [x] More fonts - - [x] Generic screen.h stuff (don't assume 1920x1080 32bpp) - - [x] Multi vbe mode support - - [x] Setup on boot - - [ ] Different font size support - -- [x] Math - - [x] Trigonometry - - [x] Sine - - [x] Cosine - - [x] Tangent - - [x] Cotangent - - [x] Arc (inverse) versions - - [x] Hyperbolic versions - - [x] Absolute value - - [?] isOdd() 🗿 - - [x] Exponential fn (e^x) - - [x] Logarithm - - [x] Power - - [x] Square Root - - [x] Floor - - [x] Round - - [x] Ceiling - - [x] Sign - - [x] INFINITY - - [x] NAN - - [x] E (eulers number) - - [x] PI - -- [ ] Filesystem - - [x] Utility for filesystem building (not just an assembly file) - - [x] Better header for file i/o (disk/filesys.h) - - [x] Filetable - - [x] A better filesystem using INodes etc. - - [x] Files - - [x] Larger than one sector (512B) - - [x] Any file size (Not multiples of 512B) - - [x] Filetypes - - [ ] Directories - - [x] File tree - - [x] Dir Entries - - [ ] cd command - - [ ] Links?? - - [ ] Symbolic - - [ ] Hard - -- [ ] System Calls - - [x] Sleep() - - [x] Write() - - [x] Read() - - [x] Open() - - [x] Close() - - [x] Malloc() - - [x] Free() - - [x] Seek() - - [ ] Tell() - - [ ] Exit() - -- [ ] Shell - - [ ] Separate file/program - - [ ] ';' separated commands - - [ ] I/O Redirection with '<' '>' - - [x] Display directory in prompt - - [ ] Custom prompts - - [ ] Variables - - [ ] Enviromental/Global - - [ ] Normal - - [ ] Commands - - [x] echo - - [x] clear - - [x] help - - [x] ls - - [x] exit - - [ ] touch (make file) - - [ ] rm - - [ ] mkdir (add dirs first) - - [x] reboot - - [ ] cd - -- [ ] Standard I/O stuff - - [ ] stdin - - [x] stdout - - [ ] stderr - -- [ ] User (or system) programs - - [x] Loading them - - [_] Running them - - [x] Exit back to kernel/shell - - [x] Let them use libs - - [x] Proper include files (LibC?) - - [x] argc, argv[] - -- [ ] Userspace programs - - [ ] Shell - - [x] Calculator - - [ ] Calendar - -- [ ] Code Editor - - [ ] Text editor - - [ ] Syntax highlighting - - [ ] Saving/Loading - - [ ] Hex editor - -- [ ] Assembler/Compiler - - [ ] Assembler - - [ ] Compiler (probably C) - - [ ] Standard lib - -- [ ] Finish all todos -- [ ] Refactoring!!! -- [ ] Can it run DOOM? -- [ ] Games - - [ ] Minesweeper - - [ ] Solitaire - - [ ] Tetris - -- [ ] Write an OS in kern (The FINAL Todo) +- [ ] Write an OS in kern. +- [ ] Finish all the TODOs diff --git a/docs/magic-addreses.txt b/docs/magic-addreses.txt new file mode 100644 index 0000000..3dbf630 --- /dev/null +++ b/docs/magic-addreses.txt @@ -0,0 +1,8 @@ +Magic addresses +=============== + +This is a list of magic addreses that are used in kern. +The goal is to minimize the number of these addreses. + +0x1000 - Memory map location, bootloader.memmap is a pointer to here + diff --git a/kernel/include/bootloader.h b/kernel/include/bootloader.h new file mode 100644 index 0000000..ccf5cde --- /dev/null +++ b/kernel/include/bootloader.h @@ -0,0 +1,44 @@ +#ifndef _BOOTLOADER_H +#define _BOOTLOADER_H + +#include + +// Boot protocols +#define BOOT_UNKNOWN 0 // Unknown +#define BOOT_MB1 1 // MultiBoot 1 +#define BOOT_MB2 2 // MultiBoot 2 +#define BOOT_LIMINE 3 // Limine + +struct boot_memmapEntry { + uint64_t base; + uint64_t size; + uint32_t type; + uint32_t attr; +}; + +/* + * Some values may not be provided by the bootloader, in this case + * pointers will be NULL and integer values will be 0 if applicable. + * Some unprovided values may also be implied. Eg.: + * If 'memmap = NULL' then 'memmapLen' doesn't matter. + */ +struct boot_info { + uint32_t memLower; + uint32_t memUpper; + struct boot_memmapEntry* memmap; + size_t memmapLen; +}; + +/* + * This functions arguments depend on the boot protocol provided. + * This is the reason for the varargs thing. It runs on of the functions + * defined after it. + */ +int boot_init(int type, ...); + +int boot_init_mb1(void* ptr, uint32_t magic); +// TODO: +// int boot_init_mb2(...); +// int boot_init_limine(...); + +#endif diff --git a/kernel/include/kernel.h b/kernel/include/kernel.h index 5973ea0..021e802 100644 --- a/kernel/include/kernel.h +++ b/kernel/include/kernel.h @@ -76,17 +76,15 @@ extern uint32_t __kernel_start, __kernel_end; /* * Logging and errors */ -// TODO: Logging with printk() -// TODO: Log levels & pr_*() wrappers for printk() -#define BUG() (panic("BUG()")) +// TODO +#define printk(_s) NULL +#define pr_dbg(_s) NULL +#define pr_wrn(_s) NULL +#define pr_err(_s) NULL +#define panic(_s) NULL +#define BUG() NULL #define WARN() NULL #define BUG_ON(_e) ((_e) ? BUG() : NULL) #define WARN_ON(_e) ((_e) ? WARN() : NULL) -#include -__noreturn static inline void panic(char* s) { - serial_puts(COM1, s); - __asm__ volatile("cli"); - while (1) __asm__ volatile ("hlt"); -} #endif diff --git a/kernel/include/multiboot.h b/kernel/include/multiboot.h index 269cf9b..8629624 100644 --- a/kernel/include/multiboot.h +++ b/kernel/include/multiboot.h @@ -68,7 +68,7 @@ /* is there a symbol table loaded? */ #define MULTIBOOT_INFO_AOUT_SYMS 0x00000010 /* is there an ELF section header table? */ -#define MULTIBOOT_INFO_ELF_SHDR 0X00000020 +#define MULTIBOOT_INFO_ELF_SHDR 0x00000020 /* is there a full memory map? */ #define MULTIBOOT_INFO_MEM_MAP 0x00000040 diff --git a/kernel/include/pmm.h b/kernel/include/pmm.h index 65cb75e..72ac783 100644 --- a/kernel/include/pmm.h +++ b/kernel/include/pmm.h @@ -1,6 +1,15 @@ #ifndef _PMM_H #define _PMM_H -int pmm_init(); +#include + +#define PMM_BS 4096 // Block Size +#define PMM_BPB 8 // Blocks per byte + +int pmm_init(void); +void pmm_initRegion(size_t base, size_t len); +void pmm_deinitRegion(size_t base, size_t len); +void* pmm_alloc(size_t blockCount); +void pmm_free(void* ptr, size_t blockCount); #endif diff --git a/kernel/include/serial.h b/kernel/include/serial.h index 302ae8e..a580b29 100644 --- a/kernel/include/serial.h +++ b/kernel/include/serial.h @@ -8,6 +8,9 @@ #define COM3 0x3e8 #define COM4 0x2e8 +// Buffer for (v)debugf() +#define DF_BUF_LEN 2048 + int serial_init(int dev); int serial_txem(int dev); void serial_send(int dev, char data); @@ -16,4 +19,7 @@ char serial_recv(int dev); void serial_write(int dev, char* buf, size_t len); void serial_puts(int dev, char* s); +int debugf(char* fmt, ...); +int vdebugf(char* fmt, va_list args); + #endif diff --git a/kernel/linker.ld b/kernel/linker.ld index 808adea..663efa1 100644 --- a/kernel/linker.ld +++ b/kernel/linker.ld @@ -1,31 +1,41 @@ OUTPUT_FORMAT("elf32-i386") +OUTPUT_ARCH("i386"); ENTRY(_start) +/* Define correct program headers */ +PHDRS { + text PT_LOAD FLAGS((1 << 0) | (1 << 2)); /* Read, Execute */ + rodata PT_LOAD FLAGS((1 << 0)); /* Read */ + data PT_LOAD FLAGS((1 << 0) | (1 << 1)); /* Read, Write */ +} + +/* Define sections */ SECTIONS { /* 1MB is a conventional place for kernels */ . = 1M; - /* We need the multiboot header in the first 8192 bytes */ + __kernel_start = .; .text BLOCK(4K) : ALIGN(4K) { *(.multiboot) *(.text) - } + } : text - /* Read-only data */ .rodata BLOCK(4K) : ALIGN(4K) { *(.rodata) - } + } : rodata - /* Initalized r/w data */ .data BLOCK(4K) : ALIGN(4K) { *(.data) - } + } : data - /* Uninitialized r/w data and stack */ .bss BLOCK(4K) : ALIGN(4K) { *(COMMON) *(.bss) - } + } : data + __kernel_end = .; - . = 4M; + /DISCARD/ : { + *(.eh_frame) + *(.note*) + } } diff --git a/kernel/src/bootloader.c b/kernel/src/bootloader.c new file mode 100644 index 0000000..ad998d1 --- /dev/null +++ b/kernel/src/bootloader.c @@ -0,0 +1,47 @@ +#include +#include +#include + +struct boot_info bootloader = { 0 }; + +int boot_init(int type, ...) { + va_list args; + va_start(args, type); + + switch (type) { + case BOOT_UNKNOWN: return 1; + case BOOT_MB1: return boot_init_mb1(va_arg(args, void*), va_arg(args, uint32_t)); + case BOOT_MB2: return 1; + case BOOT_LIMINE: return 1; + } + + // We got an invalid boot protocol + return 1; +} + +int boot_init_mb1(void* ptr, uint32_t magic) { + multiboot_info_t* mbi = ptr; + + if (magic != 0xBADB002) return 1; + + // Memory info + if (mbi->flags & MULTIBOOT_INFO_MEMORY) { + bootloader.memLower = mbi->mem_lower; + bootloader.memUpper = mbi->mem_upper; + } + + // Memory map + if (mbi->flags & MULTIBOOT_INFO_MEM_MAP) { + uint32_t memmap = mbi->mmap_addr; + uint32_t offset = 0; + while (offset < mbi->mmap_length) { + multiboot_memory_map_t* entry = (multiboot_memory_map_t*)(memmap + offset); + offset += entry->size; + + + } + } + + return 0; +} + diff --git a/kernel/src/kernel.c b/kernel/src/kernel.c index 50fc878..045e7b2 100644 --- a/kernel/src/kernel.c +++ b/kernel/src/kernel.c @@ -1,19 +1,17 @@ #include #include #include -#include #include -#define _hlt() while (1) __asm__ volatile ("cli; hlt"); +/* TODO: Commented out stuff */ __noreturn void kmain(void* ptr, uint32_t magic) { - // Init with MultiBoot 1, this populates the global bootloader struct - //if (boot_init(BOOT_MB1, ptr, magic) != 0) panic("Unsupporred bootloader."); + if (boot_init(BOOT_MB1, ptr, magic) != 0) panic("Unsupporred bootloader."); // Serial console for debugging serial_init(COM1); - serial_puts(COM1, "\x1b[0H\x1b[Jkern.\n"); + debugf("\x1b[H\x1b[J\x1b[0mkern. \x1b[35m(serial console)\x1b[0m\n\n"); // VGA tty thingy tty_init(); @@ -29,8 +27,9 @@ void kmain(void* ptr, uint32_t magic) { debugf("Basic initialization complete!\n"); - /* TODO: Commented out stuff */ - panic("kmain() reached end."); + + // Temporary loop since panic() does not halt + while (1); } diff --git a/kernel/src/pmm.c b/kernel/src/pmm.c index 850f59e..c814e86 100644 --- a/kernel/src/pmm.c +++ b/kernel/src/pmm.c @@ -1,4 +1,94 @@ +#include +#include #include -int pmm_init() { return 0; } +// Helpers +#define SET_BLOCK(_b) memmap[(_b) / 32] |= (1 << ((_b) % 32)) +#define USET_BLOCK(_b) memmap[(_b) / 32] &= ~(1 << ((_b) % 32)) +#define TEST_BLOCK(_b) ((memmap[(_b) % 32] & (1 << ((_b) % 32))) ? 1 : 0) + +// Memory manager bitmap +uint32_t* memmap = NULL; +size_t usedBlocks = 0; +size_t maxBlocks = 0; + +// TODO: improve these hardcoded values +int pmm_init(void) { + memmap = NULL; // Memory map location + usedBlocks = 0; + maxBlocks = 0; // TODO + return 0; +} + +int findFreeBlocks(size_t blockCount) { + if (blockCount == 0) return -1; + + uint32_t max = maxBlocks / 32; + uint32_t freeCount = 0; + for (size_t i = 0; i < max; i++) { + // We don't have to check, cause it's all reserved + if (memmap[i] == 0xffffffff) continue; + + for (uint8_t j = 0; j < 32; j++) { + if (TEST_BLOCK(i * PMM_BPB + j)) freeCount++; + else freeCount = 0; + + if (freeCount >= blockCount) return i * PMM_BPB + j; + } + } + + // We didn't find enough free memory :( + return -1; +} + +void pmm_initRegion(size_t base, size_t len) { + uint32_t align = base / PMM_BS; + uint32_t blockCount = len / PMM_BS; + + while (blockCount-- > 0) { + USET_BLOCK(align); + align++; + usedBlocks--; + } + + SET_BLOCK(0); +} + +void pmm_deinitRegion(size_t base, size_t len) { + uint32_t align = base / PMM_BS; + uint32_t blockCount = len / PMM_BS; + + while (blockCount-- > 0) { + align++; + SET_BLOCK(align); // We can't increment here, because macros -_(._.)_- + usedBlocks++; + } + + SET_BLOCK(0); +} + +void* pmm_alloc(size_t blockCount) { + if ((maxBlocks - usedBlocks) < blockCount) return NULL; + + int startBlock = findFreeBlocks(blockCount); + if (startBlock == -1) return NULL; + + for (size_t i = 0; i < blockCount; i++) { + SET_BLOCK(startBlock + i); + usedBlocks++; + } + + return (void*)(startBlock * PMM_BS); +} + +void pmm_free(void* ptr, size_t blockCount) { + size_t startBlock = (size_t)ptr / PMM_BS; + + for (size_t i = 0; i < blockCount; i++) { + USET_BLOCK(startBlock + i); + usedBlocks--; + } + + SET_BLOCK(0); // Make sure block 0 is always set +}