From 123382eace57154fbf1e40476bdaed1aa398bf6d Mon Sep 17 00:00:00 2001 From: Bananymous Date: Tue, 15 Nov 2022 21:42:14 +0200 Subject: [PATCH] Fixes :) --- kernel/Makefile | 4 +- kernel/arch/i386/tty.cpp | 32 ++++-- kernel/include/kernel/kprint.h | 150 +++++++++++++++++++++++++++++ kernel/include/kernel/multiboot.h | 51 ++++++++++ kernel/include/kernel/tty.h | 1 - kernel/kernel/{ssp.cpp => SSP.cpp} | 8 +- kernel/kernel/kernel.cpp | 49 +++------- kernel/kernel/panic.cpp | 5 +- libc/Makefile | 1 + libc/include/string.h | 2 + libc/stdio/printf.cpp | 51 ++++++---- libc/stdio/putchar.cpp | 2 + libc/string/strstr.cpp | 9 ++ 13 files changed, 299 insertions(+), 66 deletions(-) create mode 100644 kernel/include/kernel/kprint.h create mode 100644 kernel/include/kernel/multiboot.h rename kernel/kernel/{ssp.cpp => SSP.cpp} (91%) create mode 100644 libc/string/strstr.cpp diff --git a/kernel/Makefile b/kernel/Makefile index 81aeb0c4..552fa0d7 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -31,7 +31,7 @@ KERNEL_OBJS=\ $(KERNEL_ARCH_OBJS) \ kernel/kernel.o \ kernel/panic.o \ -kernel/ssp.o \ +kernel/SSP.o \ OBJS=\ $(ARCHDIR)/crti.o \ @@ -59,7 +59,7 @@ banan-os.kernel: $(OBJS) $(ARCHDIR)/linker.ld grub-file --is-x86-multiboot banan-os.kernel $(ARCHDIR)/crtbegin.o $(ARCHDIR)/crtend.o: - OBJ=`$(CXX) $(CFLAGS) $(LDFLAGS) -print-file-name=$(@F)` && cp "$$OBJ" $@ + OBJ=`$(CXX) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -print-file-name=$(@F)` && cp "$$OBJ" $@ .cpp.o: $(CXX) -MD -c $< -o $@ $(CFLAGS) $(CPPFLAGS) diff --git a/kernel/arch/i386/tty.cpp b/kernel/arch/i386/tty.cpp index d7232278..4c11f86a 100644 --- a/kernel/arch/i386/tty.cpp +++ b/kernel/arch/i386/tty.cpp @@ -1,13 +1,16 @@ +#include +#include #include #include "vga.h" #include #include +#include -static constexpr size_t VGA_WIDTH = 80; -static constexpr size_t VGA_HEIGHT = 25; -static uint16_t* const VGA_MEMORY = (uint16_t*)0xB8000; +static size_t VGA_WIDTH; +static size_t VGA_HEIGHT; +static uint16_t* VGA_MEMORY; static size_t terminal_row; static size_t terminal_col; @@ -29,11 +32,29 @@ void terminal_clear() void terminal_initialize() { + if (s_multiboot_info->flags & (1 << 12)) + { + const framebuffer_info_t& fb = s_multiboot_info->framebuffer; + VGA_WIDTH = fb.width; + VGA_HEIGHT = fb.height; + VGA_MEMORY = (uint16_t*)fb.addr; + } + else + { + VGA_WIDTH = 80; + VGA_HEIGHT = 25; + VGA_MEMORY = (uint16_t*)0xB8000; + } + terminal_row = 0; terminal_col = 0; terminal_color = vga_entry_color(VGA_COLOR_WHITE, VGA_COLOR_BLACK); terminal_buffer = VGA_MEMORY; terminal_clear(); + + if (s_multiboot_info->flags & (1 << 12)) + if (s_multiboot_info->framebuffer.type != 2) + Kernel::panic("Invalid framebuffer_type in multiboot info"); } void terminal_setcolor(uint8_t color) @@ -118,8 +139,5 @@ void terminal_write(const char* data, size_t size) void terminal_writestring(const char* data) { - size_t len = 0; - while (data[len]) - len++; - terminal_write(data, len); + terminal_write(data, strlen(data)); } \ No newline at end of file diff --git a/kernel/include/kernel/kprint.h b/kernel/include/kernel/kprint.h new file mode 100644 index 00000000..c2314bfb --- /dev/null +++ b/kernel/include/kernel/kprint.h @@ -0,0 +1,150 @@ +#pragma once + +#include + +#include +#include + + +template +static void kprint_signed(T value) +{ + if (value == 0) + { + terminal_putchar('0'); + return; + } + + char buffer[32]; + char* ptr = buffer + sizeof(buffer); + bool sign = false; + + if (value < 0) + { + sign = true; + *(--ptr) = ((value % 10 + 10) % 10) + '0'; + value /= 10; + } + + while (value) + { + *(--ptr) = (value % 10) + '0'; + value /= 10; + } + if (sign) + *(--ptr) = '-'; + + terminal_write(ptr, sizeof(buffer) - (ptr - buffer)); +} + +template +static void kprint_unsigned(T value) +{ + if (value == 0) + { + terminal_putchar('0'); + return; + } + + char buffer[32]; + char* ptr = buffer + sizeof(buffer); + + while (value) + { + *(--ptr) = (value % 10) + '0'; + value /= 10; + } + + terminal_write(ptr, sizeof(buffer) - (ptr - buffer)); +} + + +template +static void kprint_val(T) +{ + terminal_writestring(""); +} + +static void kprint(const char* format) +{ + terminal_writestring(format); +} + +template +static void kprint(const char* format, Arg arg, Args... args) +{ + const char* next = strstr(format, "{}"); + if (next == NULL) + { + terminal_writestring(format); + return; + } + terminal_write(format, next - format); + kprint_val(arg); + kprint(next + 2, args...); +} + +template<> void kprint_val(short int value) { kprint_signed(value); } +template<> void kprint_val( int value) { kprint_signed(value); } +template<> void kprint_val(long int value) { kprint_signed(value); } +template<> void kprint_val(long long int value) { kprint_signed(value); } + +template<> void kprint_val(unsigned short int value) { kprint_unsigned(value); } +template<> void kprint_val(unsigned int value) { kprint_unsigned(value); } +template<> void kprint_val(unsigned long int value) { kprint_unsigned(value); } +template<> void kprint_val(unsigned long long int value) { kprint_unsigned(value); } + +template<> void kprint_val( char value) { terminal_putchar(value); } +template<> void kprint_val(signed char value) { kprint_signed(value); } +template<> void kprint_val(unsigned char value) { kprint_unsigned(value); } + +template<> void kprint_val(const char* value) { terminal_writestring(value); } +template<> void kprint_val(char* value) { terminal_writestring(value); } + + + +static char bits_to_hex(uint8_t val) +{ + val = val & 0xF; + if (val < 10) + return val + '0'; + return val + 'a' - 10; +} + +template<> void kprint_val(void* value) +{ + terminal_write("0x", 2); + + if constexpr(sizeof(void*) == sizeof(uint32_t)) + { + uint32_t addr = (uint32_t)value; + terminal_putchar(bits_to_hex(addr >> 28)); + terminal_putchar(bits_to_hex(addr >> 24)); + terminal_putchar(bits_to_hex(addr >> 20)); + terminal_putchar(bits_to_hex(addr >> 16)); + terminal_putchar(bits_to_hex(addr >> 12)); + terminal_putchar(bits_to_hex(addr >> 8)); + terminal_putchar(bits_to_hex(addr >> 4)); + terminal_putchar(bits_to_hex(addr >> 0)); + } + else + { + uint64_t addr = (uint64_t)value; + terminal_putchar(bits_to_hex(addr >> 60)); + terminal_putchar(bits_to_hex(addr >> 56)); + terminal_putchar(bits_to_hex(addr >> 52)); + terminal_putchar(bits_to_hex(addr >> 48)); + terminal_putchar(bits_to_hex(addr >> 44)); + terminal_putchar(bits_to_hex(addr >> 40)); + terminal_putchar(bits_to_hex(addr >> 36)); + terminal_putchar(bits_to_hex(addr >> 32)); + terminal_putchar(bits_to_hex(addr >> 28)); + terminal_putchar(bits_to_hex(addr >> 24)); + terminal_putchar(bits_to_hex(addr >> 20)); + terminal_putchar(bits_to_hex(addr >> 16)); + terminal_putchar(bits_to_hex(addr >> 12)); + terminal_putchar(bits_to_hex(addr >> 8)); + terminal_putchar(bits_to_hex(addr >> 4)); + terminal_putchar(bits_to_hex(addr >> 0)); + } +} diff --git a/kernel/include/kernel/multiboot.h b/kernel/include/kernel/multiboot.h new file mode 100644 index 00000000..143c1a73 --- /dev/null +++ b/kernel/include/kernel/multiboot.h @@ -0,0 +1,51 @@ +#pragma once + +#include + +struct framebuffer_info_t +{ + uint64_t addr; + uint32_t pitch; + uint32_t width; + uint32_t height; + uint8_t bpp; + uint8_t type; + uint8_t color_info[6]; +} __attribute__((packed)); + +struct multiboot_memory_map_t +{ + uint32_t size; + uint64_t base_addr; + uint64_t length; + uint32_t type; +} __attribute__((packed)); + +// https://www.gnu.org/software/grub/manual/multiboot/multiboot.html#Boot-information-format +struct multiboot_info_t +{ + uint32_t flags; + uint32_t mem_lower; + uint32_t mem_upper; + uint32_t boot_device; + uint32_t cmdline; + uint32_t mods_count; + uint32_t mods_addr; + uint32_t syms[4]; + uint32_t mmap_length; + uint32_t mmap_addr; + uint32_t drives_length; + uint32_t drives_addr; + uint32_t config_table; + uint32_t boot_loader_name; + uint32_t apm_table; + uint32_t vbe_control_info; + uint32_t vbe_mode_info; + uint16_t vbe_mode; + uint16_t vbe_interface_seg; + uint16_t vbe_interface_off; + uint16_t vbe_interface_len; + framebuffer_info_t framebuffer; +} __attribute__((packed)); + +extern multiboot_info_t* s_multiboot_info; diff --git a/kernel/include/kernel/tty.h b/kernel/include/kernel/tty.h index 15f5fa7b..107bed9e 100644 --- a/kernel/include/kernel/tty.h +++ b/kernel/include/kernel/tty.h @@ -3,7 +3,6 @@ #include #include - void terminal_initialize(); void terminal_putchar(char c); void terminal_write(const char* data, size_t size); diff --git a/kernel/kernel/ssp.cpp b/kernel/kernel/SSP.cpp similarity index 91% rename from kernel/kernel/ssp.cpp rename to kernel/kernel/SSP.cpp index 02bc8763..0f3d3b77 100644 --- a/kernel/kernel/ssp.cpp +++ b/kernel/kernel/SSP.cpp @@ -9,10 +9,14 @@ #endif uintptr_t __stack_chk_guard = STACK_CHK_GUARD; - + +__BEGIN_DECLS + __attribute__((noreturn)) void __stack_chk_fail(void) { printf("Stack smashing detected\n"); abort(); -} \ No newline at end of file +} + +__END_DECLS \ No newline at end of file diff --git a/kernel/kernel/kernel.cpp b/kernel/kernel/kernel.cpp index c4f02efb..bf74ba5d 100644 --- a/kernel/kernel/kernel.cpp +++ b/kernel/kernel/kernel.cpp @@ -1,60 +1,43 @@ #include #include +#include #include #include +#include -#include #include #include #define DISABLE_INTERRUPTS() asm volatile("cli") #define ENABLE_INTERRUPTS() asm volatile("sti") -// https://www.gnu.org/software/grub/manual/multiboot/multiboot.html#Boot-information-format -struct multiboot_info_t -{ - uint32_t flags; - uint32_t mem_lower; - uint32_t mem_upper; - uint32_t boot_device; - uint32_t cmdline; - uint32_t mods_count; - uint32_t mods_addr; - uint32_t syms[4]; - uint32_t mmap_length; - uint32_t mmap_addr; - uint32_t drives_length; - uint32_t drives_addr; - uint32_t config_table; - uint32_t boot_loader_name; - uint32_t apm_table; - uint32_t vbe_control_info; - uint32_t vbe_mode_info; - uint16_t vbe_mode; - uint16_t vbe_interface_seg; - uint16_t vbe_interface_off; - uint16_t vbe_interface_len; - uint8_t framebuffer[22]; -#if 1 - uint8_t color_info[6]; -#endif -} __attribute__((packed)); +multiboot_info_t* s_multiboot_info; extern "C" void kernel_main(multiboot_info_t* mbi, uint32_t magic) { DISABLE_INTERRUPTS(); + s_multiboot_info = mbi; + terminal_initialize(); if (magic != 0x2BADB002) Kernel::panic("Invalid magic in multiboot"); - if (mbi->flags & 0b00100000) + + if (!(mbi->flags & (1 << 6))) + Kernel::panic("Bootloader did not provide memory map"); + + for (uint32_t i = 0; i < mbi->mmap_length;) { - printf("mmap_length: %d\n", mbi->mmap_length); - printf("mmap_addr: %p\n", mbi->mmap_addr); + multiboot_memory_map_t* mmmt = (multiboot_memory_map_t*)(mbi->mmap_addr + i); + if (mmmt->type == 1) + kprint("Size: {}, Addr: {}, Length: {}, Type: {}\n", mmmt->size, (void*)mmmt->base_addr, (void*)mmmt->length, mmmt->type); + + i += mmmt->size + sizeof(uint32_t); } printf("Hello from the kernel!\n"); + kprint("Hello from the kernel!\n"); } \ No newline at end of file diff --git a/kernel/kernel/panic.cpp b/kernel/kernel/panic.cpp index 52d9635f..65a8ce71 100644 --- a/kernel/kernel/panic.cpp +++ b/kernel/kernel/panic.cpp @@ -1,5 +1,5 @@ #include -#include +#include namespace Kernel { @@ -7,8 +7,7 @@ namespace Kernel __attribute__((__noreturn__)) void panic(const char* message) { - terminal_writestring("Kernel panic: "); - terminal_writestring(message); + kprint("Kernel panic: {}", message); asm volatile("hlt"); __builtin_unreachable(); } diff --git a/libc/Makefile b/libc/Makefile index 840bae5c..6bd2e6a5 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -40,6 +40,7 @@ string/memset.o \ string/strcpy.o \ string/strlen.o \ string/strncpy.o \ +string/strstr.o \ HOSTEDOBJS=\ $(ARCH_HOSTEDOBJS) \ diff --git a/libc/include/string.h b/libc/include/string.h index 67a136c3..1675097d 100644 --- a/libc/include/string.h +++ b/libc/include/string.h @@ -14,4 +14,6 @@ size_t strlen(const char*); char* strcpy(char* __restrict, const char* __restrict); char* strncpy(char* __restrict, const char* __restrict, size_t); +char* strstr(const char*, const char*); + __END_DECLS \ No newline at end of file diff --git a/libc/stdio/printf.cpp b/libc/stdio/printf.cpp index 3cad1868..429eecbf 100644 --- a/libc/stdio/printf.cpp +++ b/libc/stdio/printf.cpp @@ -33,6 +33,7 @@ static bool print_integer(T value, size_t& out_len) buffer[len++] = (value % 10) + '0'; value /= 10; } + if (sign) buffer[len++] = '-'; if (len == 0) @@ -52,34 +53,39 @@ static bool print_integer(T value, size_t& out_len) return true; } -static char bits_to_hex(unsigned char bits) +static char bits_to_hex(int bits, bool upper_case) { if (bits < 10) return bits + '0'; - return bits - 10 + 'a'; + return bits - 10 + (upper_case ? 'A' : 'a'); } -static bool print_ptr(void* ptr, size_t& out_len) +template +static bool print_hex(T value, bool upper_case, size_t& out_len) { - ptrdiff_t addr = reinterpret_cast(ptr); + char buffer[16] {}; + int len = 0; - char buffer[2 + sizeof(ptrdiff_t) * 2]; - buffer[0] = '0'; - buffer[1] = 'x'; - - size_t bytes = sizeof(ptrdiff_t); - - for (size_t i = 1; i <= bytes; i++) + while (value) { - unsigned char byte = (addr >> ((bytes - i) * 8)) & 0xff; - buffer[i * 2 + 0] = bits_to_hex(byte >> 4); - buffer[i * 2 + 1] = bits_to_hex(byte & 0b1111); + buffer[len++] = bits_to_hex(value & 0xF, upper_case); + value >>= 4; } - if (!print(buffer, 2 + bytes * 2)) + if (len == 0) + buffer[len++] = '0'; + + for (int i = 0; i < len / 2; i++) + { + char temp = buffer[i]; + buffer[i] = buffer[len - i - 1]; + buffer[len - i - 1] = temp; + } + + if (!print(buffer, len)) return false; - out_len = 2 + bytes * 2; + out_len = len; return true; } @@ -149,12 +155,21 @@ int printf(const char* __restrict format, ...) return -1; written += len; } + else if (*format == 'x' || *format == 'X') + { + format++; + unsigned int value = va_arg(args, unsigned int); + size_t len; + if (!print_hex(value, *(format - 1) == 'X', len)) + return -1; + written += len; + } else if (*format == 'p') { format++; - void* const ptr = va_arg(args, void*); + void* ptr = va_arg(args, void*); size_t len; - if (!print_ptr(ptr, len)) + if (!print("0x", 2) || !print_hex((ptrdiff_t)ptr, false, len)) return -1; written += len; } diff --git a/libc/stdio/putchar.cpp b/libc/stdio/putchar.cpp index d473e824..dcdb42d9 100644 --- a/libc/stdio/putchar.cpp +++ b/libc/stdio/putchar.cpp @@ -2,6 +2,7 @@ #if defined(__is_libk) #include +#include #else #include #endif @@ -9,6 +10,7 @@ int putchar(int c) { #if defined(__is_libk) + Kernel::panic("Please use kprint() instead of stdio"); char ch = (char)c; terminal_write(&ch, sizeof(ch)); #else diff --git a/libc/string/strstr.cpp b/libc/string/strstr.cpp new file mode 100644 index 00000000..3094eb9c --- /dev/null +++ b/libc/string/strstr.cpp @@ -0,0 +1,9 @@ +#include + +char* strstr(const char* haystack, const char* needle) +{ + for (size_t i = 0; haystack[i]; i++) + if (memcmp(haystack + i, needle, strlen(needle)) == 0) + return (char*)haystack + i; + return NULL; +} \ No newline at end of file