diff --git a/.vscode/settings.json b/.vscode/settings.json index 0300e4e..fe3c9e9 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,7 @@ { "files.associations": { "types.h": "c", - "vga_text_mode.h": "c" + "vga_text_mode.h": "c", + "kmsg.h": "c" } } diff --git a/Makefile b/Makefile index 219db38..35e3688 100644 --- a/Makefile +++ b/Makefile @@ -33,8 +33,27 @@ sboot_object_files = $(sboot_asm_object_files) shade_bin_ldfile = src/linker.ld +version = 0.1.1-alpha +stream = shade-development +git_build = $(shell git rev-parse --short HEAD) +date = $(shell date) +codename = willow + default: run +.FORCE: + +include/shade/version.h: .FORCE + echo "#ifndef VERSION_H" > include/shade/version.h + echo "#define VERSION_H" >> include/shade/version.h + echo "// This file was autogenerated by the shadeOS build system. It should not be modified." >> include/shade/version.h + echo "#define SHADE_OS_KERNEL_VERSION \"$(version)\"" >> include/shade/version.h + echo "#define SHADE_OS_KERNEL \"$(stream)\"" >> include/shade/version.h + echo "#define SHADE_OS_BUILD \"$(git_build)\"" >> include/shade/version.h + echo "#define SHADE_OS_COMPILE_DATE \"$(date)\"" >> include/shade/version.h + echo "#define SHADE_OS_CODENAME \"$(codename)\"" >> include/shade/version.h + echo "#endif" >> include/shade/version.h + bin/shade.iso: bin/shade.bin cp bin/shade.bin src/iso/boot/shade.bin grub-mkrescue src/iso/ -o $@ @@ -64,4 +83,4 @@ run: clean bin/shade.iso clean: rm -rf bin/* - rm -rf obj/* \ No newline at end of file + rm -rf obj/* diff --git a/bin/shade.bin b/bin/shade.bin index a5688a2..67dff2a 100755 Binary files a/bin/shade.bin and b/bin/shade.bin differ diff --git a/bin/shade.iso b/bin/shade.iso index bc0b69a..5874439 100644 Binary files a/bin/shade.iso and b/bin/shade.iso differ diff --git a/include/printf.h b/include/printf.h index e58f666..c67832f 100644 --- a/include/printf.h +++ b/include/printf.h @@ -57,8 +57,8 @@ void _putchar(char character); * \param format A string that specifies the format of the output * \return The number of characters that are written into the array, not counting the terminating null character */ -#define printf printf_ -int printf_(const char* format, ...); +#define kprintf kprintf_ +int kprintf_(const char* format, ...); /** @@ -68,8 +68,8 @@ int printf_(const char* format, ...); * \param format A string that specifies the format of the output * \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character */ -#define sprintf sprintf_ -int sprintf_(char* buffer, const char* format, ...); +#define ksprintf ksprintf_ +int ksprintf_(char* buffer, const char* format, ...); /** @@ -82,10 +82,10 @@ int sprintf_(char* buffer, const char* format, ...); * null character. A value equal or larger than count indicates truncation. Only when the returned value * is non-negative and less than count, the string has been completely written. */ -#define snprintf snprintf_ -#define vsnprintf vsnprintf_ -int snprintf_(char* buffer, size_t count, const char* format, ...); -int vsnprintf_(char* buffer, size_t count, const char* format, va_list va); +#define ksnprintf ksnprintf_ +#define kvsnprintf kvsnprintf_ +int ksnprintf_(char* buffer, size_t count, const char* format, ...); +int kvsnprintf_(char* buffer, size_t count, const char* format, va_list va); /** @@ -94,8 +94,8 @@ int vsnprintf_(char* buffer, size_t count, const char* format, va_list va); * \param va A value identifying a variable arguments list * \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character */ -#define vprintf vprintf_ -int vprintf_(const char* format, va_list va); +#define kvprintf kvprintf_ +int kvprintf_(const char* format, va_list va); /** @@ -106,7 +106,7 @@ int vprintf_(const char* format, va_list va); * \param format A string that specifies the format of the output * \return The number of characters that are sent to the output function, not counting the terminating null character */ -int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...); +int kfctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...); #ifdef __cplusplus diff --git a/include/shade/cansid.h b/include/shade/cansid.h new file mode 100644 index 0000000..946f76d --- /dev/null +++ b/include/shade/cansid.h @@ -0,0 +1,26 @@ +#ifndef CANSID_H +#define CANSID_H + +typedef struct { + enum { + CANSID_ESC, + CANSID_BRACKET, + CANSID_PARSE, + CANSID_BGCOLOR, + CANSID_FGCOLOR, + CANSID_EQUALS, + CANSID_ENDVAL, + } state; + unsigned char style; + unsigned char next_style; +} cansid_state; + +typedef struct { + unsigned char style; + unsigned char ascii; +} color_char; + +cansid_state cansid_init(void); +color_char cansid_process(cansid_state *state, char x); + +#endif \ No newline at end of file diff --git a/include/shade/kmsg.h b/include/shade/kmsg.h new file mode 100644 index 0000000..9f57212 --- /dev/null +++ b/include/shade/kmsg.h @@ -0,0 +1,10 @@ +#ifndef KMSG_H +#define KMSG_H + +#include + +void kmsg_ok(char* format, ...); +void kmsg_warn(char* format, ...); +void kmsg_fail(char* format, ...); + +#endif \ No newline at end of file diff --git a/include/shade/platform/drivers/vga_text_mode.h b/include/shade/platform/drivers/vga_text_mode.h index deb00fb..abf8f2a 100644 --- a/include/shade/platform/drivers/vga_text_mode.h +++ b/include/shade/platform/drivers/vga_text_mode.h @@ -4,6 +4,7 @@ #define REG_SCREEN_DATA 0x3d5 #include +#include enum { PRINT_COLOR_BLACK = 0, @@ -24,11 +25,6 @@ enum { PRINT_COLOR_WHITE = 15, }; -typedef struct ansi_code_struct { - int flag; - int color; -} ansi_color_code_t; - const static int NUM_COLS = 80; const static int NUM_ROWS = 25; @@ -37,19 +33,6 @@ struct Char { char color; }; -static bool is_parsing_ansi_string = false; -static bool ansi_string_found_bracket = false; - -static bool ansi_string_found_semi = false; -static bool ansi_string_found_m = false; - -static bool ansi_string_found_number = false; - -static int _flag = 0; -static int _color = 0; - -static int working_num = 0; - void clear_row(int row); void clear_all(); @@ -63,6 +46,6 @@ void set_cursor_pos(int col, int row); void kernel_msg_ok(char* msg); -void handle_ansi_code(ansi_color_code_t code); +void init_state(); #endif \ No newline at end of file diff --git a/include/shade/platform/interrupts/isr.h b/include/shade/platform/interrupts/isr.h index b8309fb..26c1fc8 100644 --- a/include/shade/platform/interrupts/isr.h +++ b/include/shade/platform/interrupts/isr.h @@ -57,7 +57,7 @@ ds */ __attribute__((noreturn)) -void exception_handler(isr_xframe_t frame); +void exception_handler(uint8_t vector, uint16_t err); __attribute__((noreturn)) void interrupt_handler(isr_xframe_t frame); diff --git a/include/shade/version.h b/include/shade/version.h new file mode 100644 index 0000000..b2db027 --- /dev/null +++ b/include/shade/version.h @@ -0,0 +1,9 @@ +#ifndef VERSION_H +#define VERSION_H +// This file was autogenerated by the shadeOS build system. It should not be modified. +#define SHADE_OS_KERNEL_VERSION "0.1.1-alpha" +#define SHADE_OS_KERNEL "shade-development" +#define SHADE_OS_BUILD "b4e6b2e" +#define SHADE_OS_COMPILE_DATE "Sun May 15 05:41:17 PM EDT 2022" +#define SHADE_OS_CODENAME "willow" +#endif diff --git a/obj/kernel/kernel.o b/obj/kernel/kernel.o index 8d4907e..feca931 100644 Binary files a/obj/kernel/kernel.o and b/obj/kernel/kernel.o differ diff --git a/src/kernel/cansid.c b/src/kernel/cansid.c new file mode 100644 index 0000000..93aba66 --- /dev/null +++ b/src/kernel/cansid.c @@ -0,0 +1,114 @@ +#include +#include + +#include + +#define ESC '\x1B' + +cansid_state cansid_init(void) +{ + cansid_state rv = { + .state = CANSID_ESC, + .style = 0x0F, + .next_style = 0x0F + }; + return rv; +} + +static inline unsigned char cansid_convert_color(unsigned char color) +{ + const unsigned char lookup_table[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; + return lookup_table[(int)color]; +} + +color_char cansid_process(cansid_state *state, char x) +{ + color_char rv = { + .style = state->style, + .ascii = '\0' + }; + switch (state->state) { + case CANSID_ESC: + if (x == ESC) + state->state = CANSID_BRACKET; + else { + rv.ascii = x; + } + break; + case CANSID_BRACKET: + if (x == '[') + state->state = CANSID_PARSE; + else { + state->state = CANSID_ESC; + rv.ascii = x; + } + break; + case CANSID_PARSE: + if (x == '3') { + state->state = CANSID_FGCOLOR; + } else if (x == '4') { + state->state = CANSID_BGCOLOR; + } else if (x == '0') { + state->state = CANSID_ENDVAL; + state->next_style = 0x0F; + } else if (x == '1') { + state->state = CANSID_ENDVAL; + state->next_style |= (1 << 3); + } else if (x == '=') { + state->state = CANSID_EQUALS; + } else { + state->state = CANSID_ESC; + state->next_style = state->style; + rv.ascii = x; + } + break; + case CANSID_BGCOLOR: + if (x >= '0' && x <= '7') { + state->state = CANSID_ENDVAL; + state->next_style &= 0x1F; + state->next_style |= cansid_convert_color(x - '0') << 4; + } else { + state->state = CANSID_ESC; + state->next_style = state->style; + rv.ascii = x; + } + break; + case CANSID_FGCOLOR: + if (x >= '0' && x <= '7') { + state->state = CANSID_ENDVAL; + state->next_style &= 0xF8; + state->next_style |= cansid_convert_color(x - '0'); + } else { + state->state = CANSID_ESC; + state->next_style = state->style; + rv.ascii = x; + } + break; + case CANSID_EQUALS: + if (x == '1') { + state->state = CANSID_ENDVAL; + state->next_style &= ~(1 << 3); + } else { + state->state = CANSID_ESC; + state->next_style = state->style; + rv.ascii = x; + } + break; + case CANSID_ENDVAL: + if (x == ';') { + state->state = CANSID_PARSE; + } else if (x == 'm') { + // Finish and apply styles + state->state = CANSID_ESC; + state->style = state->next_style; + } else { + state->state = CANSID_ESC; + state->next_style = state->style; + rv.ascii = x; + } + break; + default: + break; + } + return rv; +} \ No newline at end of file diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index c7144de..aa7f52f 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -2,47 +2,43 @@ #include #include #include +#include #include +#include + +// Welcome to Shade! +// shadeOS kernel version 0.2.2 +// Running on shade-development +// shadeOS willow, build b4e5b2e, compiled blah void kernel_welcome() { - printf("Welcome to "); - print_set_color(PRINT_COLOR_CYAN, PRINT_COLOR_BLACK); - printf("Shade"); - print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK); - printf("!\nshadeOS kernel version "); - print_set_color(PRINT_COLOR_YELLOW, PRINT_COLOR_BLACK); - printf("0.2.2\n"); - print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK); - printf("Running on "); - print_set_color(PRINT_COLOR_YELLOW, PRINT_COLOR_BLACK); - printf("shade-development\n"); - print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK); + kprintf("Welcome to \x1b[0;36mShade\x1b[0m!\n"); + kprintf("shadeOS kernel version \x1b[0;33m%s\x1b[0m\n", SHADE_OS_KERNEL_VERSION); + kprintf("Running on \x1b[0;33m%s\x1b[0m\n", SHADE_OS_KERNEL); + kprintf("shadeOS %s (%s), compiled %s\n", SHADE_OS_CODENAME, SHADE_OS_BUILD, SHADE_OS_COMPILE_DATE); } // kMain void kmain() { // Initialize screen buffer struct Char* buffer = (struct Char*) 0xb8000; + init_state(); clear_all(); // Clear screen set_cursor_pos(0, 0); // Set cursor position print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK); // Set print color // welcome messages - kernel_msg_ok("Initialized display successfully\n"); + kmsg_ok("Initialized display successfully\n"); kernel_welcome(); - printf("Copyright (c) e3team 2022. All rights reserved.\n"); - printf("This program is provided \"as-is\" and no express or implied warranty is provided.\n"); - printf("The full license can be found at /sys/LICENCE on this system or ./LICENCE in the source tree.\n"); + kprintf("Copyright (c) e3team 2022. All rights reserved.\n"); + kprintf("This program is provided \"as-is\" and no express or implied warranty is provided.\n"); + kprintf("The full license can be found at /sys/LICENCE on this system or ./LICENCE in the source tree.\n"); pic_remap(0x20, 0x28); idt_assemble(); - kernel_msg_ok("Enabled interrupts\n"); - __asm__ __volatile__("int $2"); - - printf("ANSI code test: double \x1b[3;31m \x1b[31m \x1b[12m \x1b[0m \x1b[3;31m \n"); - printf("ansi code test done\n"); + kmsg_ok("Enabled interrupts\n"); for (;;) {} } \ No newline at end of file diff --git a/src/kernel/kmsg.c b/src/kernel/kmsg.c new file mode 100644 index 0000000..6cb9786 --- /dev/null +++ b/src/kernel/kmsg.c @@ -0,0 +1,26 @@ +#include +#include + +void kmsg_ok(char* format, ...) { + va_list args; + va_start(args, format); + char str[32767]; + kvsnprintf(str, 32767, format, args); + kprintf("[ \x1b[0;32mOK\x1b[0m ] %s\x1b[0m\n", str); +} + +void kmsg_warn(char* format, ...) { + va_list args; + va_start(args, format); + char str[32767]; + kvsnprintf(str, 32767, format, args); + kprintf("[ \x1b[0;33mWARN\x1b[0m ] %s\x1b[0m\n", str); +} + +void kmsg_fail(char* format, ...) { + va_list args; + va_start(args, format); + char str[32767]; + kvsnprintf(str, 32767, format, args); + kprintf("[ \x1b[0;31mFAIL\x1b[0m ] %s\x1b[0m\n", str); +} \ No newline at end of file diff --git a/src/kernel/platform/drivers/vga_text_mode.c b/src/kernel/platform/drivers/vga_text_mode.c index 8d77f12..f8173b5 100644 --- a/src/kernel/platform/drivers/vga_text_mode.c +++ b/src/kernel/platform/drivers/vga_text_mode.c @@ -6,6 +6,8 @@ int row = 0; int col = 0; char color = PRINT_COLOR_WHITE | PRINT_COLOR_BLACK << 4; +cansid_state state; + void clear_row(int row) { struct Char* buffer = (struct Char*) 0xb8000; @@ -48,214 +50,20 @@ void print_newline() { set_cursor_pos(col, row); } -bool is_hexchar(char character) { - switch (character) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case 'a': - case 'b': - case 'c': - case 'd': - case 'e': - case 'f': - return true; - break; - default: - return false; - break; - } -} - -bool is_digit(char ch) { - return (ch >= '0') && (ch <= '9'); -} - -unsigned int _atoi(const char** str) { - unsigned int i = 0U; - while (is_digit(**str)) { - i = i * 10U + (unsigned int)(*((*str)++) - '0'); - } - return i; -} - - void print_char(char character) { - // ANSI parsing - // 1. is the current char \x1b? - if (character == '\x1b') { - // are we already printing an ansi string? - if (is_parsing_ansi_string) { - // string is invalid now - is_parsing_ansi_string = false; - return; - } else { - // no! set flag and continue - is_parsing_ansi_string = true; - return; - } - } - - // 2. are we working on an ansi string right now? - if (is_parsing_ansi_string) { - if (!ansi_string_found_bracket && character != '[') { - // string is invalid, stop - is_parsing_ansi_string = false; - ansi_string_found_bracket = false; - working_num = 0; - ansi_string_found_m = false; - ansi_string_found_semi = false; - ansi_string_found_number = false; - _flag = 0; - _color = 0; - _print_char(character); - return; - } else { - // found bracket - ansi_string_found_bracket = true; - return; - } - if (ansi_string_found_bracket && !(ansi_string_found_semi || ansi_string_found_m)) { - // looking for flag OR color, idk yet - if (ansi_string_found_number) { - if (character == 'm') { - if (ansi_string_found_m) { - // invalid - is_parsing_ansi_string = false; - ansi_string_found_bracket = false; - working_num = 0; - ansi_string_found_m = false; - ansi_string_found_semi = false; - ansi_string_found_number = false; - _flag = 0; - _color = 0; - _print_char(character); - return; - } - ansi_string_found_m = true; - // string is done - _color = working_num; - ansi_color_code_t code; - code.flag = _flag; - code.color = color; - handle_ansi_code(code); - is_parsing_ansi_string = false; - ansi_string_found_bracket = false; - working_num = 0; - ansi_string_found_m = false; - ansi_string_found_semi = false; - ansi_string_found_number = false; - _flag = 0; - _color = 0; - return; - } else if (character == ';') { - if (ansi_string_found_semi) { - // invalid - is_parsing_ansi_string = false; - ansi_string_found_bracket = false; - working_num = 0; - ansi_string_found_m = false; - ansi_string_found_semi = false; - ansi_string_found_number = false; - _flag = 0; - _color = 0; - _print_char(character); - return; - } - _flag = working_num; - working_num = 0; - ansi_string_found_number = false; - ansi_string_found_semi = true; - return; - } - } - if (!is_digit(character)) { - // not a digit, print out and discard existing string - is_parsing_ansi_string = false; - ansi_string_found_bracket = false; - working_num = 0; - ansi_string_found_m = false; - ansi_string_found_semi = false; - ansi_string_found_number = false; - _print_char(character); - return; - } else { - // is digit, add to working - working_num *= 10; - working_num += _atoi(character); - ansi_string_found_number = true; - } - } - if (ansi_string_found_bracket && ansi_string_found_semi && !ansi_string_found_m) { - if (ansi_string_found_number) { - if (character == 'm') { - if (ansi_string_found_m) { - // invalid - is_parsing_ansi_string = false; - ansi_string_found_bracket = false; - working_num = 0; - ansi_string_found_m = false; - ansi_string_found_semi = false; - ansi_string_found_number = false; - _flag = 0; - _color = 0; - _print_char(character); - return; - } - ansi_string_found_m = true; - // string is done - _color = working_num; - ansi_color_code_t code; - code.flag = _flag; - code.color = _color; - handle_ansi_code(code); - is_parsing_ansi_string = false; - ansi_string_found_bracket = false; - working_num = 0; - ansi_string_found_m = false; - ansi_string_found_semi = false; - ansi_string_found_number = false; - _flag = 0; - _color = 0; - return; - } - if (!_is_digit(character)) { - // not a digit, print out and discard existing string - is_parsing_ansi_string = false; - ansi_string_found_bracket = false; - working_num = 0; - ansi_string_found_m = false; - ansi_string_found_semi = false; - ansi_string_found_number = false; - _flag = 0; - _color = 0; - _print_char(character); - return; - } else { - // is digit, add to working - working_num *= 10; - working_num += _atoi(character); - ansi_string_found_number = true; - } - } - } - } - - _print_char(character); - return; + color_char ch = cansid_process(&state, character); + color = ch.style; + _print_char(ch.ascii); } void _print_char(char character) { struct Char* buffer = (struct Char*) 0xb8000; + if (character == 0) { + return; + } + if (character == '\n') { print_newline(); return; @@ -315,14 +123,6 @@ void kernel_msg_ok(char* msg) { print_str(msg); } - -void handle_ansi_code(ansi_color_code_t code) { - char s[50]; - itoa(code.flag, s); - print_str("ansi code: ["); - print_str(s); - print_str(";"); - itoa(code.color, s); - print_str(s); - print_str("m found\n"); +void init_state() { + state = cansid_init(); } \ No newline at end of file diff --git a/src/kernel/platform/interrupts/int.asm b/src/kernel/platform/interrupts/int.asm index 624dc1e..fb80710 100644 --- a/src/kernel/platform/interrupts/int.asm +++ b/src/kernel/platform/interrupts/int.asm @@ -61,30 +61,24 @@ mov cr0, rax %endmacro isr_xframe_assembler: - push rbp - mov rbp, rsp - pushagrd - pushacrd - mov ax, ds - push rax - push qword 0 - mov ax, 0x10 - mov ds, ax - mov es, ax + + pop rdi ; Pop the interrupt number into rdi (first argument) + pop rsi ; Pop the error code into rsi (second argument) + + mov ax, ds ; Put ds into ax + push rax ; Push it to the stack + mov ax, 0x10 ; Set kernel data segment + mov ds, ax ; set kernel data segment + mov es, ax ; set kernel data segment mov ss, ax - lea rdi, [rsp + 0x10] call exception_handler - pop rax pop rax mov ds, ax mov es, ax - popacrd - popagrd - pop rbp - add rsp, 0x10 + iretq isr_no_err_stub 0 diff --git a/src/kernel/platform/interrupts/isr.c b/src/kernel/platform/interrupts/isr.c index 8476771..2790c63 100644 --- a/src/kernel/platform/interrupts/isr.c +++ b/src/kernel/platform/interrupts/isr.c @@ -1,11 +1,11 @@ #include #include -void exception_handler(isr_xframe_t frame) { - printf(" %i: cpu: check_exception 0x%x err_code => %i\n", err_count, frame.base_frame.vector, frame.base_frame.error_code); +void exception_handler(uint8_t vector, uint16_t err) { + kprintf(" %i: cpu: check_exception 0x%x err_code => %x\n", err_count, vector, err); err_count++; if (err_count > ERR_MAX) { - printf("cpu: ierr hit err_max, halt\n"); + kprintf("cpu: ierr hit err_max, halt\n"); __asm__ __volatile__("cli; hlt"); } } \ No newline at end of file diff --git a/src/libc/printf.c b/src/libc/printf.c index 916c9d9..8a68695 100644 --- a/src/libc/printf.c +++ b/src/libc/printf.c @@ -868,7 +868,7 @@ static int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const /////////////////////////////////////////////////////////////////////////////// -int printf_(const char* format, ...) +int kprintf_(const char* format, ...) { va_list va; va_start(va, format); @@ -879,7 +879,7 @@ int printf_(const char* format, ...) } -int sprintf_(char* buffer, const char* format, ...) +int ksprintf_(char* buffer, const char* format, ...) { va_list va; va_start(va, format); @@ -889,7 +889,7 @@ int sprintf_(char* buffer, const char* format, ...) } -int snprintf_(char* buffer, size_t count, const char* format, ...) +int ksnprintf_(char* buffer, size_t count, const char* format, ...) { va_list va; va_start(va, format); @@ -899,20 +899,20 @@ int snprintf_(char* buffer, size_t count, const char* format, ...) } -int vprintf_(const char* format, va_list va) +int kvprintf_(const char* format, va_list va) { char buffer[1]; return _vsnprintf(_out_char, buffer, (size_t)-1, format, va); } -int vsnprintf_(char* buffer, size_t count, const char* format, va_list va) +int kvsnprintf_(char* buffer, size_t count, const char* format, va_list va) { return _vsnprintf(_out_buffer, buffer, count, format, va); } -int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...) +int kfctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...) { va_list va; va_start(va, format);