diff --git a/kernel/arch/x86/boot/boot.c b/kernel/arch/x86/boot/boot.c index 60310c8..933e98e 100644 --- a/kernel/arch/x86/boot/boot.c +++ b/kernel/arch/x86/boot/boot.c @@ -19,14 +19,14 @@ void banner(void) { - tty_write("Welcome to MoonOS\n"); - tty_write( - "\n" - " _____ _____ _____ \n" - "| |___ ___ ___| | __| \n" - "| | | | . | . | | | |__ | \n" - "|_|_|_|___|___|_|_|_____|_____| \n" - "\n"); + trace(TRACE_BOOT, "Welcome to MoonOS\n"); + trace(TRACE_BOOT, + "\n" + " _____ _____ _____ \n" + "| |___ ___ ___| | __| \n" + "| | | | . | . | | | |__ | \n" + "|_|_|_|___|___|_|_|_____|_____| \n" + "\n"); } NORETURN void boot(void) diff --git a/kernel/arch/x86/devices/tty.c b/kernel/arch/x86/devices/tty.c index 84fb6a5..bca077a 100644 --- a/kernel/arch/x86/devices/tty.c +++ b/kernel/arch/x86/devices/tty.c @@ -30,7 +30,7 @@ void arch_tty_init(uint64_t fb_addr, uint16_t fb_width, uint16_t fb_height, // clang-format on } -void arch_tty_write(string_view str) +void arch_tty_write(StringView str) { - flanterm_write(ft_ctx, str, strlen(str)); + flanterm_write(ft_ctx, str.data, str.length); } diff --git a/kernel/arch/x86/devices/tty.h b/kernel/arch/x86/devices/tty.h index e893006..7469eeb 100644 --- a/kernel/arch/x86/devices/tty.h +++ b/kernel/arch/x86/devices/tty.h @@ -9,6 +9,6 @@ void arch_tty_init(uint64_t fb_addr, uint16_t fb_width, uint16_t fb_height, uint8_t fb_red_mask_shift, uint8_t fb_green_mask_size, uint8_t fb_green_mask_shift, uint8_t fb_blue_mask_size, uint8_t fb_blue_mask_shift); -void arch_tty_write(string_view str); +void arch_tty_write(StringView str); #endif // TTY_H \ No newline at end of file diff --git a/kernel/arch/x86/int/interrupts.c b/kernel/arch/x86/int/interrupts.c index 993f22d..38a9f3a 100644 --- a/kernel/arch/x86/int/interrupts.c +++ b/kernel/arch/x86/int/interrupts.c @@ -11,37 +11,37 @@ isr_t isr_handler_array[256] = {0}; bool can_return = false; -static string_view exception_messages[] = { - "Type: (#DE) Division Exception", - "Type: (#DB) Debug Exception", - "Type: (NONE) NMI interrupt (Non Maskable Interrupt)", - "Type: (#BP) Breakpoint Exception", - "Type: (#OF) Into detected Overflow Exception", - "Type: (#BR) BOUND Range Exceeded", - "Type: (#UD) Invalid Opcode (Undefined Opcode)", - "Type: (#NM) Device Not Available (No Math Coprocessor)", - "Type: (#DF) Double Fault", - "Type: (NONE) Coprocessor Segment Overrun (reserved)", - "Type: (#TS) Invalid TSS", - "Type: (#NP) Segment Not Present", - "Type: (#SS) Stack-Segment Fault", - "Type: (#GP) General Protection Fault", - "Type: (#PF) Page Fault", - "Type: (NONE) Unknown interrupt", - "Type: (#CF) Coprocessor fault", - "Type: (#AC) Alignment check", - "Type: (NONE) Reserved", - "Type: (NONE) Reserved", - "Type: (NONE) Reserved", - "Type: (NONE) Reserved", - "Type: (NONE) Reserved", - "Type: (NONE) Reserved", - "Type: (NONE) Reserved", - "Type: (NONE) Reserved", - "Type: (NONE) Reserved", - "Type: (NONE) Reserved", - "Type: (NONE) Reserved", - "Type: (NONE) Reserved"}; +static StringView exception_messages[] = { + str_literal("Type: (#DE) Division Exception"), + str_literal("Type: (#DB) Debug Exception"), + str_literal("Type: (NONE) NMI interrupt (Non Maskable Interrupt)"), + str_literal("Type: (#BP) Breakpoint Exception"), + str_literal("Type: (#OF) Into detected Overflow Exception"), + str_literal("Type: (#BR) BOUND Range Exceeded"), + str_literal("Type: (#UD) Invalid Opcode (Undefined Opcode)"), + str_literal("Type: (#NM) Device Not Available (No Math Coprocessor)"), + str_literal("Type: (#DF) Double Fault"), + str_literal("Type: (NONE) Coprocessor Segment Overrun (reserved)"), + str_literal("Type: (#TS) Invalid TSS"), + str_literal("Type: (#NP) Segment Not Present"), + str_literal("Type: (#SS) Stack-Segment Fault"), + str_literal("Type: (#GP) General Protection Fault"), + str_literal("Type: (#PF) Page Fault"), + str_literal("Type: (NONE) Unknown interrupt"), + str_literal("Type: (#CF) Coprocessor fault"), + str_literal("Type: (#AC) Alignment check"), + str_literal("Type: (NONE) Reserved"), + str_literal("Type: (NONE) Reserved"), + str_literal("Type: (NONE) Reserved"), + str_literal("Type: (NONE) Reserved"), + str_literal("Type: (NONE) Reserved"), + str_literal("Type: (NONE) Reserved"), + str_literal("Type: (NONE) Reserved"), + str_literal("Type: (NONE) Reserved"), + str_literal("Type: (NONE) Reserved"), + str_literal("Type: (NONE) Reserved"), + str_literal("Type: (NONE) Reserved"), + str_literal("Type: (NONE) Reserved")}; void isr_handler(struct iframe *regs) { @@ -54,7 +54,7 @@ void isr_handler(struct iframe *regs) serial_set_color(BASH_RED); debug(true, "ERROR: %s (err_code %ld) | %lx\n", - exception_messages[regs->isr_number], + exception_messages[regs->isr_number].data, regs->error_code, cr2_read()); // for(;;); @@ -137,8 +137,9 @@ void install_isr(uint8_t base, isr_t handler) isr_handler_array[base] = handler; } else - printk( - "INT", "The interrupt ( %d ) has already been registered!\n", base); + trace(TRACE_INT, + "The interrupt (%d) has already been registered!\n", + base); } void uninstall_isr(uint8_t base) diff --git a/kernel/panic.c b/kernel/panic.c index 0188597..120b90c 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -1,3 +1,4 @@ +#define PR_MODULE "panic" #include "panic.h" #include #include @@ -17,8 +18,8 @@ NORETURN void __panic(size_t bp, size_t sp, string_view fmt, ...) override_quiet_boot(); - printk("panic", "\n\033[31mA kernel panic has occurred\033[39m\n"); - tty_write("*** \033[97mReason: %s\033[39m ***\n", panic_buff); + trace(TRACE_ERROR, "\n\033[31mA kernel panic has occurred\033[39m\n"); + trace(TRACE_ERROR, "*** \033[97mReason: %s\033[39m ***\n", panic_buff); debug(false, "A kernel panic has occurred\n*** \033[97mReason: %s\033[39m ***\n", panic_buff); @@ -29,11 +30,11 @@ NORETURN void __panic(size_t bp, size_t sp, string_view fmt, ...) } size_t frame_size = bp - sp; - printk("stackdump", - "Dumping %s's stackframe\nStackframe size: 0x%x\n", - sym_lookup(res.trace_results[1]).name, - frame_size); - tty_write("\t\t \t \n"); + trace(TRACE_ERROR, + "Dumping %s's stackframe\nStackframe size: 0x%x\n", + sym_lookup(res.trace_results[1]).name, + frame_size); + trace(TRACE_ERROR, "\t\t \t \n"); // The larger the stackframe the less likely the chance of seeing messages // printed earlier due to the terminal scrolling. 0x18 was chosen randomly. @@ -43,10 +44,11 @@ NORETURN void __panic(size_t bp, size_t sp, string_view fmt, ...) // Dump stackframe of the function that called panic() for (size_t i = 0; i < frame_size; i++) { - tty_write("%lx: %p %p\n", - bp, - *(size_t *)(bp), - *(size_t *)(bp + sizeof(size_t))); + trace(TRACE_ERROR, + "%lx: %p %p\n", + bp, + *(size_t *)(bp), + *(size_t *)(bp + sizeof(size_t))); bp += sizeof(size_t) * 2; } diff --git a/kernel/platform/acpi/x86/acpi.c b/kernel/platform/acpi/x86/acpi.c index 8845fd8..2ce4c98 100644 --- a/kernel/platform/acpi/x86/acpi.c +++ b/kernel/platform/acpi/x86/acpi.c @@ -49,7 +49,7 @@ AcpiTable acpi_find_table(string_view identifier) } } - printk("acpi", "Could not find table '%s'\n", identifier); + trace(TRACE_HARDWARE, "Could not find table '%s'\n", identifier); return NULL; } diff --git a/kernel/platform/acpi/x86/madt/madt.c b/kernel/platform/acpi/x86/madt/madt.c index 82258f9..8b4b62b 100644 --- a/kernel/platform/acpi/x86/madt/madt.c +++ b/kernel/platform/acpi/x86/madt/madt.c @@ -44,8 +44,8 @@ struct apic_device_info madt_init(void *madt_base) pic_disable(); enumarate_apic_devices(&madt); - trace(TRACE_MISC, "OEM String: '%s'\n", oem_str); - trace(TRACE_MISC, "OEM Table ID: '%s'\n", oem_table_id); + trace(TRACE_HARDWARE, "OEM String: '%s'\n", oem_str); + trace(TRACE_HARDWARE, "OEM Table ID: '%s'\n", oem_table_id); return apic_dev; } @@ -61,7 +61,7 @@ static void enumarate_apic_devices(madt_t **madt) { case 0 ... 5: { - trace(TRACE_MISC, + trace(TRACE_HARDWARE, "Detected %s\n", interrupt_device_id_map[*madt_interrupt_devices]); @@ -84,12 +84,12 @@ static void enumarate_apic_devices(madt_t **madt) } case 9: - printk("madt", "Detected x2APIC\n"); + trace(TRACE_HARDWARE, "Detected x2APIC\n"); madt_interrupt_devices += madt_interrupt_devices[1]; break; default: - trace(TRACE_MISC, + trace(TRACE_HARDWARE, "Invalid interrupt device detected, got %d, expected 0-5 " "or 9\n", *madt_interrupt_devices); diff --git a/kernel/printk.c b/kernel/printk.c index 9788bf1..2cca824 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -23,7 +23,7 @@ void printk_init(bool verbose_boot, HandoverFramebuffer fb) is_verbose_boot = verbose_boot; } -void printk(string_view status, string_view fmt, ...) +void printk(StringView status, StringView fmt, ...) { if (unlikely(!is_verbose_boot)) return; @@ -31,21 +31,18 @@ void printk(string_view status, string_view fmt, ...) char buffer[512]; va_list arg; va_start(arg, fmt); - vsnprintf((string)&buffer, (size_t)-1, fmt, arg); + vsnprintf(buffer, sizeof(buffer), fmt.data, arg); va_end(arg); - tty_write("[core#%d] %s: %s", current_cpu(), status, buffer); -} - -void tty_write(string_view fmt, ...) -{ - char buffer[512]; - va_list arg; - va_start(arg, fmt); - vsnprintf((string)&buffer, (size_t)-1, fmt, arg); - va_end(arg); + char output[512]; + snprintf(output, + sizeof(output), + "[core#%d] %s: %s", + current_cpu(), + status.data, + buffer); - arch_tty_write((string_view)&buffer); + arch_tty_write(str(output)); } // Note: This should only be called when information diff --git a/kernel/printk.h b/kernel/printk.h index 72d64b2..df1fcff 100644 --- a/kernel/printk.h +++ b/kernel/printk.h @@ -2,6 +2,7 @@ #define FMT_PRINTK_H #include +#include #include #include @@ -16,39 +17,40 @@ debug(true, x, __VA_ARGS__); \ } while (0) -#define trace(bitmask, ...) \ - do \ - { \ - if (bitmask & TRACE_MASK) \ - printk(PR_MODULE, __VA_ARGS__); \ +#define trace(bitmask, fmt, ...) \ + do \ + { \ + if (bitmask & TRACE_MASK) \ + printk(str(PR_MODULE), str(fmt), ##__VA_ARGS__); \ } while (0) #define TRACE_MASK (TRACE_ALL) enum { - TRACE_BOOT = (1 << 0), - TRACE_INT = (1 << 1), - TRACE_DEBUG = (1 << 2), - TRACE_SYSCALL = (1 << 3), - TRACE_MISC = (1 << 4), // For logs with no specific category - TRACE_TASK = (1 << 5), - TRACE_SERVICE = (1 << 6), - TRACE_ELF = (1 << 7), - TRACE_SLAB = (1 << 8), - TRACE_BUDDY = (1 << 9), - TRACE_TLSF = (1 << 10), - TRACE_ALLOC = (1 << 11), - TRACE_IPC = (1 << 12), - TRACE_CAP = (1 << 13), + TRACE_BOOT = (1 << 0), + TRACE_INT = (1 << 1), + TRACE_DEBUG = (1 << 2), + TRACE_SYSCALL = (1 << 3), + TRACE_MISC = (1 << 4), // For logs with no specific category + TRACE_TASK = (1 << 5), + TRACE_SERVICE = (1 << 6), + TRACE_ELF = (1 << 7), + TRACE_SLAB = (1 << 8), + TRACE_BUDDY = (1 << 9), + TRACE_TLSF = (1 << 10), + TRACE_ALLOC = (1 << 11), + TRACE_IPC = (1 << 12), + TRACE_CAP = (1 << 13), + TRACE_ERROR = (1 << 14), + TRACE_HARDWARE = (1 << 15), TRACE_ALL = ~0, TRACE_NONE = 0, }; -void printk(string_view status, string_view fmt, ...); void printk_init(bool verbose_boot, HandoverFramebuffer fb); -void tty_write(string_view fmt, ...); +void printk(StringView status, StringView fmt, ...); // Note: This should only be called when information // must be shown, a kernel panic for example diff --git a/kernel/trace/sym.c b/kernel/trace/sym.c index 8888633..54c683d 100644 --- a/kernel/trace/sym.c +++ b/kernel/trace/sym.c @@ -1,16 +1,17 @@ +#define PR_MODULE "sym" #if defined(__x86_64__) #include "sym.h" -#include #include #include #include +#include extern SymbolTable symbol_table[]; SymbolTable sym_lookup(uint64_t address) { uint64_t corrected_address = 0; - uint64_t index_new = 0; + uint64_t index_new = 0; for (int i = 0;; i++) { @@ -24,15 +25,14 @@ SymbolTable sym_lookup(uint64_t address) if (sym_addr > corrected_address) { corrected_address = sym_addr; - index_new = i; + index_new = i; } } if (sym_addr == 0xFFFFFFFF) { - return (SymbolTable){ - .addr = corrected_address, - .name = symbol_table[index_new].name}; + return (SymbolTable){.addr = corrected_address, + .name = symbol_table[index_new].name}; } } } @@ -58,7 +58,7 @@ int64_t find_symbol_by_name(string name) void backtrace_symbol(uint64_t address) { SymbolTable sym = sym_lookup(address); - printk("backtrace", "%llx - %s\n", sym.addr, sym.name); + trace(TRACE_MISC, "%llx - %s\n", sym.addr, sym.name); debug(false, "%llx - %s\n", sym.addr, sym.name); } #endif \ No newline at end of file diff --git a/libs/base/cstring.h b/libs/base/cstring.h new file mode 100644 index 0000000..6c4cf04 --- /dev/null +++ b/libs/base/cstring.h @@ -0,0 +1,14 @@ +#ifndef LIB_KERNEL_CSTRING_H +#define LIB_KERNEL_CSTRING_H + +#include + +int strcmp(const char *str1, const char *str2); +int strncmp(string_view str1, string_view str2, size_t n); +char *strcpy(char *dest, string_view src); +char *strcat(char *a, char *b); +uint64_t strlen(string_view s); +char *strrev(char *src); +bool isdigit(int c); + +#endif // LIB_KERNEL_CSTRING_H \ No newline at end of file diff --git a/libs/base/sources/assert.c b/libs/base/sources/assert.c index eb2ff37..bda11c0 100644 --- a/libs/base/sources/assert.c +++ b/libs/base/sources/assert.c @@ -1,12 +1,25 @@ +#define PR_MODULE "assert" #include "assert.h" +#include #include #include -#include -void __assert_impl(string_view file, uint64_t line, string_view func, string_view desc) +void __assert_impl(string_view file, uint64_t line, string_view func, + string_view desc) { - printk("ASSERT", "%s:%d: %s: Assertion `%s' failed", (char *)file, line, func, desc); - debug(true, "ASSERT: %s:%d: %s: Assertion `%s' failed", (char *)file, line, func, desc); - + trace(TRACE_ERROR, + "%s:%d: %s: Assertion `%s' failed", + (char *)file, + line, + func, + desc); + + debug(true, + "ASSERT: %s:%d: %s: Assertion `%s' failed", + (char *)file, + line, + func, + desc); + arch_halt_cpu(); } \ No newline at end of file diff --git a/libs/base/sources/cstring.c b/libs/base/sources/cstring.c new file mode 100644 index 0000000..3a1c648 --- /dev/null +++ b/libs/base/sources/cstring.c @@ -0,0 +1,111 @@ +#include "cstring.h" + +// Compare two strings. +/* Returns: + -1 if ( len(str1) > len(str2) ) or ( len(str2) > len(str1) ) + 0 if str1 == str2 + 1 otherwise +*/ +int strcmp(const char *str1, const char *str2) +{ + int i = 0; + int failed = 0; + + while (str1[i] != '\0' && str2[i] != '\0') + { + if (str1[i] != str2[i]) + { + failed = 1; + + break; + } + + i++; + } + + // did loop exit due to unequal lengths? + if ((str1[i] == '\0' && str2[i] != '\0') || // len( str2 ) > len( str1 ) + (str1[i] != '\0' && str2[i] == '\0')) // len( str1 ) > len( str2 ) + { + failed = -1; + } + + return failed; +} + +int strncmp(const char *str1, const char *str2, size_t n) +{ + for (size_t i = 0; i < n && str1; i++) + { + if (str1[i] != str2[i]) + return -1; + } + return 0; +} + +// Copy the NULL-terminated string src into dest, and return dest +char *strcpy(char *dest, const char *src) +{ + int n = -1; + int len = strlen(src); + do + { + ++n; + memcpy((uint8_t *)dest, (uint8_t *)src, n); + } while (n < len); + + dest[n] = 0; // Null terminate the stri + return dest; +} + +char *strcat(char *a, char *b) +{ + char *ptr = a + strlen(a); + + while (*b != '\0') + *ptr++ = *b++; + + // null terminate destination string + *ptr = '\0'; + + return a; +} + +// Get the string length +uint64_t strlen(const char *s) +{ + uint64_t len = 0; + + while (*s++ != '\0') + { + len++; + } + + return len; +} + +char *strrev(char *src) +{ + static char temp; + int src_string_index = 0; + int last_char = strlen(src) - 1; + + for (; src_string_index < last_char; src_string_index++) + { + temp = src[src_string_index]; // Save current character + src[src_string_index] = + src[last_char]; // Swap out the current char with the last char + src[last_char] = + temp; // Swap out last character with the current character + last_char--; + } + + src[strlen(src) - 1 + 1] = 0; + + return src; +} + +bool isdigit(int c) +{ + return (c >= '0' && c <= '9'); +} diff --git a/libs/base/sources/string.c b/libs/base/sources/string.c index aec072b..319a9d1 100644 --- a/libs/base/sources/string.c +++ b/libs/base/sources/string.c @@ -1,111 +1,42 @@ #include "base/string.h" +#include "base/assert.h" -// Compare two strings. -/* Returns: - -1 if ( len(str1) > len(str2) ) or ( len(str2) > len(str1) ) - 0 if str1 == str2 - 1 otherwise -*/ -int strcmp(string_view str1, string_view str2) +StringView make_string_view(const char *str) { - int i = 0; - int failed = 0; - - while (str1[i] != '\0' && str2[i] != '\0') - { - if (str1[i] != str2[i]) - { - failed = 1; - - break; - } - - i++; - } - - // did loop exit due to unequal lengths? - if ((str1[i] == '\0' && str2[i] != '\0') || // len( str2 ) > len( str1 ) - (str1[i] != '\0' && str2[i] == '\0')) // len( str1 ) > len( str2 ) - { - failed = -1; - } - - return failed; -} - -int strncmp(string_view str1, string_view str2, size_t n) -{ - for (size_t i = 0; i < n && str1; i++) - { - if (str1[i] != str2[i]) - return -1; - } - return 0; +#if defined(HEAVY_ASSERTS) + assert(str != NULL && "Bad string pointer"); + assert(strlen(str) > 0 && "Bad length"); +#else + if (str == NULL) + return (StringView){0}; +#endif + + return (StringView){ + .length = strlen(str), + .data = str, + }; } -// Copy the NULL-terminated string src into dest, and return dest -char *strcpy(char *dest, string_view src) +StringView make_string_view_from_string(const String *str) { - int n = -1; - int len = strlen(src); - do - { - ++n; - memcpy((uint8_t *)dest, (uint8_t *)src, n); - } while (n < len); - - dest[n] = 0; // Null terminate the stri - return dest; + return (StringView){ + .length = str->length, + .data = str->data, + }; } -char *strcat(char *a, char *b) +StringView make_string_view_from_array(const char arr[], size_t len) { - char *ptr = a + strlen(a); - - while (*b != '\0') - *ptr++ = *b++; - - // null terminate destination string - *ptr = '\0'; - - return a; -} - -// Get the string length -uint64_t strlen(string_view s) -{ - uint64_t len = 0; - - while (*s++ != '\0') - { - len++; - } - - return len; -} - -char *strrev(char *src) -{ - static char temp; - int src_string_index = 0; - int last_char = strlen(src) - 1; - - for (; src_string_index < last_char; src_string_index++) - { - temp = src[src_string_index]; // Save current character - src[src_string_index] = - src[last_char]; // Swap out the current char with the last char - src[last_char] = - temp; // Swap out last character with the current character - last_char--; - } - - src[strlen(src) - 1 + 1] = 0; - - return src; -} - -bool isdigit(int c) -{ - return (c >= '0' && c <= '9'); -} +#if defined(HEAVY_ASSERTS) + assert(arr != NULL && "Bad string pointer"); + assert(len > 0 && "Bad length"); +#else + if (arr == NULL) + return (StringView){0}; +#endif + + return (StringView){ + .length = len, + .data = arr, + }; +} \ No newline at end of file diff --git a/libs/base/string.h b/libs/base/string.h index 5b785c2..6d4a8d8 100644 --- a/libs/base/string.h +++ b/libs/base/string.h @@ -2,14 +2,36 @@ #define LIB_KERNEL_STRING_H #include +#include +#include -int strcmp(string_view str1, string_view str2); -int strncmp(string_view str1, string_view str2, size_t n); -char *strcpy(char *dest, string_view src); -char *strcat(char *a, char *b); -uint64_t strlen(string_view s); -char *strrev(char *src); +#define str(expression) \ + _Generic((expression), \ + char *: make_string_view, \ + const char *: make_string_view, \ + String *: make_string_view_from_string, \ + default: make_string_view_from_array)(expression) -bool isdigit(int c); +#define str_literal(literal) \ + (StringView) \ + { \ + .length = sizeof(literal) - 1, .data = literal \ + } + +typedef struct +{ + size_t length; + char *data; +} String; + +typedef struct +{ + const size_t length; + const char *const data; +} StringView; + +StringView make_string_view(const char *str); +StringView make_string_view_from_string(const String *str); +StringView make_string_view_from_array(const char arr[], size_t len); #endif // LIB_KERNEL_STRING_H \ No newline at end of file diff --git a/meta/build/make/Makefile.x86.acpi.conf b/meta/build/make/Makefile.x86.acpi.conf index 355c737..610e808 100644 --- a/meta/build/make/Makefile.x86.acpi.conf +++ b/meta/build/make/Makefile.x86.acpi.conf @@ -1,3 +1,5 @@ +DEV_FLAGS := -DHEAVY_ASSERTS + # Kernel compiler / linker flags CFLAGS := \ -I ../libs/ \ @@ -18,7 +20,8 @@ CFLAGS := \ -mno-sse2 \ -Wall \ -fno-omit-frame-pointer \ - -mno-red-zone + -mno-red-zone \ + $(DEV_FLAGS) ASMFLAGS := -felf64 -g -F dwarf -I arch/$(ARCH)/