From 119dc631e1b417eec4f0eb2d8373d034b53d0f2e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Duje=20Mihanovi=C4=87?= Date: Sat, 2 Jul 2022 14:54:37 +0200 Subject: [PATCH] kernel: Huge refactoring of tty driver The VGA-specific parts now reside solely at arch/x86/tty.c and the non-arch-specific functions (kprint*) are in kernel/kprint.c. TODO: Make kernel/kprint.c more device agnostic --- kernel/arch/x86/Makefile | 3 +- kernel/arch/x86/irq/interrupt.c | 10 +- kernel/arch/x86/tty.c | 94 +++++++++++++++++ kernel/arch/x86/tty/Makefile | 1 - kernel/arch/x86/tty/tty.c | 172 -------------------------------- kernel/include/arch/x86/tty.h | 25 +++++ kernel/include/kprint.h | 17 ++++ kernel/include/panic.h | 18 ++-- kernel/include/tty.h | 31 ------ kernel/kernel/Makefile | 2 +- kernel/kernel/kernel.c | 76 +++++++------- kernel/kernel/kprint.c | 100 +++++++++++++++++++ 12 files changed, 290 insertions(+), 259 deletions(-) create mode 100644 kernel/arch/x86/tty.c delete mode 100644 kernel/arch/x86/tty/Makefile delete mode 100644 kernel/arch/x86/tty/tty.c create mode 100644 kernel/include/arch/x86/tty.h create mode 100644 kernel/include/kprint.h delete mode 100644 kernel/include/tty.h create mode 100644 kernel/kernel/kprint.c diff --git a/kernel/arch/x86/Makefile b/kernel/arch/x86/Makefile index b164c9d..c15bef9 100644 --- a/kernel/arch/x86/Makefile +++ b/kernel/arch/x86/Makefile @@ -1,4 +1,3 @@ include arch/x86/irq/Makefile -include arch/x86/tty/Makefile -KERNEL_OBJ += $(addprefix arch/x86/, entry.o halt.o) +KERNEL_OBJ += $(addprefix arch/x86/, entry.o halt.o tty.o) diff --git a/kernel/arch/x86/irq/interrupt.c b/kernel/arch/x86/irq/interrupt.c index 5c448fe..b3c3173 100644 --- a/kernel/arch/x86/irq/interrupt.c +++ b/kernel/arch/x86/irq/interrupt.c @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include @@ -11,15 +11,15 @@ void int_handler(struct interrupt_frame *frame) { int interrupt = frame->interrupt; if (int_handler_table[interrupt] == NULL) { - kprint("WARNING: Unhandled interrupt ", 0); + kprint("WARNING: Unhandled interrupt ", VGA_YELLOW, VGA_BLACK); kprintb(interrupt, 1); - kprint(" occurred!\n", 0); + kprint(" occurred!\n", VGA_YELLOW, VGA_BLACK); } else { int ret = (*int_handler_table[interrupt])(frame); if (ret) { - kprint("WARNING: Error while handling interrupt ", 0); + kprint("WARNING: Error while handling interrupt ", VGA_YELLOW, VGA_BLACK); kprintb(interrupt, 1); - kprint("!\n", 0); + kprint("!\n", VGA_YELLOW, VGA_BLACK); } } if (interrupt >= 0x20) { diff --git a/kernel/arch/x86/tty.c b/kernel/arch/x86/tty.c new file mode 100644 index 0000000..6796594 --- /dev/null +++ b/kernel/arch/x86/tty.c @@ -0,0 +1,94 @@ +#include +#include +#include + +#define VGA_WIDTH 80 +#define VGA_HEIGHT 25 + +static int cursor_x = 0; /* keep track of where cursor is */ +static int cursor_y = 0; +static uint16_t crtc_port; + +static inline uint8_t vga_get_color(const enum vga_color fg, const enum vga_color bg) +{ + return fg&0xf | bg<<4; +} + +static inline uint16_t vga_get_char(const enum vga_color fg, const enum vga_color bg, char character) +{ + return character | vga_get_color(fg, bg)<<8; +} + +static inline char *vga_get_memory_address(int x, int y) +{ + return (char *) 0xb8000 + (y*VGA_WIDTH + x)*2; +} + +static void vga_scroll_up(void) +{ + for (int y=1; y>8); + outb(crtc_port, 0xf); + outb(crtc_port+1, cursor_address); +} + +static void vga_screen_clear(void) +{ + for (int y=0; y= VGA_WIDTH) { + cursor_x = 0; + cursor_y++; + } + + if (cursor_y >= VGA_HEIGHT) + vga_scroll_up(); + + vga_set_cursor(cursor_x, cursor_y); +} + +void vga_initialize() +{ + uint8_t vga_misc = inb(0x3cc); + if (vga_misc&1) + crtc_port = 0x3d4; + else + crtc_port = 0x3b4; + + vga_screen_clear(); +} diff --git a/kernel/arch/x86/tty/Makefile b/kernel/arch/x86/tty/Makefile deleted file mode 100644 index 0498223..0000000 --- a/kernel/arch/x86/tty/Makefile +++ /dev/null @@ -1 +0,0 @@ -KERNEL_OBJ += arch/x86/tty/tty.o diff --git a/kernel/arch/x86/tty/tty.c b/kernel/arch/x86/tty/tty.c deleted file mode 100644 index ca3212a..0000000 --- a/kernel/arch/x86/tty/tty.c +++ /dev/null @@ -1,172 +0,0 @@ -#include -#include -#include - -#define VGA_WIDTH 80 -#define VGA_HEIGHT 25 - -volatile char *video_memory = (char *) 0xB8000; /* VGA VRAM starts at 0xB8000 */ - -static int cursor_x = 0; /* keep track of where cursor is */ -static int cursor_y = 0; - -char *hex_chars = "0123456789ABCDEF"; - -void screen_clear(void) -{ - int x, y; - for ( y = 0; y < VGA_HEIGHT; y++ ) { - for ( x = 0; x < VGA_WIDTH; x++ ) { - video_memory[(y * VGA_WIDTH + x) * 2 + 1] = VGA_COLOR_LIGHT_GRAY; - video_memory[(y * VGA_WIDTH + x) * 2] = ' '; - } - } - - cursor_x = 0; - cursor_y = 0; -} - -void scroll_up(void) -{ - int x, y; - for ( y = 1; y < VGA_HEIGHT; y++ ) { - for ( x = 0; x < VGA_WIDTH; x++ ) { - video_memory[((y - 1) * VGA_WIDTH + x) * 2] = video_memory[(y * VGA_WIDTH + x) * 2]; - } - } - for ( x = 0; x < VGA_WIDTH; x++ ) { - video_memory[((VGA_HEIGHT - 1) * VGA_WIDTH + x) * 2] = ' '; - } - cursor_y = VGA_HEIGHT - 1; -} - -void kprint(const char *string, uint8_t color) -{ - char next_char; - uint8_t vga_misc_output; - uint16_t crtc_port; - next_char = *string; - - while ( next_char != 0 ) { - if ( next_char == '\n') { cursor_x = 0; cursor_y++; } - else { video_memory[(cursor_y * VGA_WIDTH + cursor_x) * 2] = next_char; video_memory[((cursor_y * VGA_WIDTH + cursor_x++) * 2)+ 1] = color != 0 ? color : VGA_COLOR_LIGHT_GRAY; } - if ( cursor_x >= VGA_WIDTH ) { cursor_x = 0; cursor_y++; } - if ( cursor_y >= VGA_HEIGHT ) { scroll_up(); } - next_char = *++string; - } - - vga_misc_output = inb(0x3CC); - if (vga_misc_output & 0x1 == 0) { - crtc_port = 0x3B4; - } else { - crtc_port = 0x3D4; - } - - outb(crtc_port, 0xE); - outb(crtc_port + 1, (cursor_y * VGA_WIDTH + cursor_x) >> 8); - outb(crtc_port, 0xF); - outb(crtc_port + 1, (cursor_y * VGA_WIDTH + cursor_x) & 0xFF); -} - -void kprintc(const char character, uint8_t color) -{ - uint8_t vga_misc_output; - uint16_t crtc_port; - - if ( character == '\n') { cursor_x = 0; cursor_y++; } - else { video_memory[(cursor_y * VGA_WIDTH + cursor_x) * 2] = character; video_memory[((cursor_y * VGA_WIDTH + cursor_x++) * 2)+ 1] = color != 0 ? color : VGA_COLOR_LIGHT_GRAY; } - if ( cursor_x >= VGA_WIDTH ) { cursor_x = 0; cursor_y++; } - if ( cursor_y >= VGA_HEIGHT ) { scroll_up(); } - - vga_misc_output = inb(0x3CC); - if (vga_misc_output & 0x1 == 0) { - crtc_port = 0x3B4; - } else { - crtc_port = 0x3D4; - } - - outb(crtc_port, 0xE); - outb(crtc_port + 1, (cursor_y * VGA_WIDTH + cursor_x) >> 8); - outb(crtc_port, 0xF); - outb(crtc_port + 1, (cursor_y * VGA_WIDTH + cursor_x) & 0xFF); - -} - -void kprintnibble(uint8_t nibble) -{ - nibble &= 0xf; - if (nibble < 0xa) - kprintc('0' + nibble, 0); - else kprintc('a' - 0xa + nibble, 0); -} - -void kprintb(uint8_t byte, int print_delm) -{ - if (print_delm) - kprint("0x", 0); - - kprintnibble(byte >> 4); - kprintnibble(byte); -} - -void kprintw(uint16_t word, int print_delm) -{ - if (print_delm) - kprint("0x", 0); - - kprintb(word >> 8, 0); - kprintb(word, 0); -} - -void kprintd(uint32_t dword, int print_delm) -{ - if (print_delm) - kprint("0x", 0); - - kprintw(dword >> 16, 0); - kprintw(dword, 0); -} - -void kprintq(uint64_t qword, int print_delm) -{ - if (print_delm) - kprint("0x", 0); - - kprintd(qword >> 32, 0); - kprintd(qword, 0); -} - -int kprintdec(uint32_t num, uint8_t color) -{ - char buffer[11]; - int digits = 10; - /* TODO: make an actual memset function to use instead of this */ - for (int i=0; i<11; i++) { - buffer[i] = 0; - } - - /* put the numbers in the buffer */ - for (int i=9; i>0 && num>0; i--) { - uint8_t currdigit = num%10; - buffer[i] = currdigit+'0'; - num /= 10; - } - - /* shift the array as much as needed */ - while (*buffer == '\0') { - digits--; - for (int i=0; i<9; i++) { - buffer[i] = buffer[i+1]; - } - } - - /* zero out any leftovers */ - if (digits < 10) { - for (int i=digits; i<10; i++) { - buffer[i] = '\0'; - } - } - - kprint(buffer, color); - return digits; -} diff --git a/kernel/include/arch/x86/tty.h b/kernel/include/arch/x86/tty.h new file mode 100644 index 0000000..a7cb8cf --- /dev/null +++ b/kernel/include/arch/x86/tty.h @@ -0,0 +1,25 @@ +#ifndef X86_TTY_H +#define X86_TTY_H + +enum vga_color { + VGA_BLACK, + VGA_BLUE, + VGA_GREEN, + VGA_TEAL, + VGA_DARK_RED, + VGA_MAGENTA, + VGA_BROWN, + VGA_LIGHT_GRAY, + VGA_DARK_GRAY, + VGA_PURPLE, + VGA_LIME, + VGA_CYAN, + VGA_BRIGHT_RED, + VGA_PINK, + VGA_YELLOW, + VGA_WHITE +}; + +extern void vga_initialize(void); +extern void vga_print_char(const char character, enum vga_color fg, enum vga_color bg); +#endif diff --git a/kernel/include/kprint.h b/kernel/include/kprint.h new file mode 100644 index 0000000..b883c14 --- /dev/null +++ b/kernel/include/kprint.h @@ -0,0 +1,17 @@ +#ifndef KPRINT_H +#define KPRINT_H + +#include +#include + +extern void tty_initialize(); +extern void kprint(const char *string, const enum vga_color fg, const enum vga_color bg); +extern void kprintc(const char character, const enum vga_color fg, const enum vga_color bg); +extern void kprintnibble(uint8_t nibble); +extern void kprintb(const uint8_t byte, const int print_delm); +extern void kprintw(const uint16_t word, const int print_delm); +extern void kprintd(const uint32_t dword, const int print_delm); +extern void kprintq(const uint64_t qword, const int print_delm); +extern int kprintdec(uint32_t num, const enum vga_color fg, const enum vga_color bg); + +#endif diff --git a/kernel/include/panic.h b/kernel/include/panic.h index f481e0c..5c4d662 100644 --- a/kernel/include/panic.h +++ b/kernel/include/panic.h @@ -4,15 +4,15 @@ extern void halt(); #define PANIC(msg) \ - kprint("PANIC (", VGA_COLOR_BRIGHT_RED);\ - kprint(msg, VGA_COLOR_BRIGHT_RED);\ - kprint(") in ", VGA_COLOR_BRIGHT_RED);\ - kprint(__FILE__, VGA_COLOR_BRIGHT_RED);\ - kprintc(':', VGA_COLOR_BRIGHT_RED);\ - kprintdec(__LINE__, VGA_COLOR_BRIGHT_RED);\ - kprintc(':', VGA_COLOR_BRIGHT_RED);\ - kprint(__func__, VGA_COLOR_BRIGHT_RED);\ - kprint("()", VGA_COLOR_BRIGHT_RED);\ + kprint("PANIC (", VGA_BRIGHT_RED, VGA_BLACK);\ + kprint(msg, VGA_BRIGHT_RED, VGA_BLACK);\ + kprint(") in ", VGA_BRIGHT_RED, VGA_BLACK);\ + kprint(__FILE__, VGA_BRIGHT_RED, VGA_BLACK);\ + kprintc(':', VGA_BRIGHT_RED, VGA_BLACK);\ + kprintdec(__LINE__, VGA_BRIGHT_RED, VGA_BLACK);\ + kprintc(':', VGA_BRIGHT_RED, VGA_BLACK);\ + kprint(__func__, VGA_BRIGHT_RED, VGA_BLACK);\ + kprint("()", VGA_BRIGHT_RED, VGA_BLACK);\ halt(); #endif diff --git a/kernel/include/tty.h b/kernel/include/tty.h deleted file mode 100644 index 87aad81..0000000 --- a/kernel/include/tty.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef TTY_H -#define TTY_H - -#include - -#define VGA_COLOR_BLACK 0x0 -#define VGA_COLOR_BLUE 0x1 -#define VGA_COLOR_GREEN 0x2 -#define VGA_COLOR_TEAL 0x3 -#define VGA_COLOR_DARK_RED 0x4 -#define VGA_COLOR_MAGENTA 0x5 -#define VGA_COLOR_BROWN 0x6 -#define VGA_COLOR_LIGHT_GRAY 0x7 -#define VGA_COLOR_DARK_GRAY 0x8 -#define VGA_COLOR_PURPLE 0x9 -#define VGA_COLOR_LIME 0xA -#define VGA_COLOR_CYAN 0xB -#define VGA_COLOR_BRIGHT_RED 0xC -#define VGA_COLOR_PINK 0xD -#define VGA_COLOR_YELLOW 0xE -#define VGA_COLOR_WHITE 0xF - -extern void screen_clear(void); -extern void kprint(const char *string, uint8_t color); -extern void kprintc(const char character, uint8_t color); -extern void kprintb(uint8_t byte, int print_delm); -extern void kprintw(uint16_t word, int print_delm); -extern void kprintd(uint32_t dword, int print_delm); -extern void kprintq(uint64_t qword, int print_delm); -extern int kprintdec(uint32_t num, uint8_t color); -#endif diff --git a/kernel/kernel/Makefile b/kernel/kernel/Makefile index 8716875..1827b72 100644 --- a/kernel/kernel/Makefile +++ b/kernel/kernel/Makefile @@ -1 +1 @@ -KERNEL_OBJ += kernel/kernel.o +KERNEL_OBJ += $(addprefix kernel/, kernel.o kprint.o) diff --git a/kernel/kernel/kernel.c b/kernel/kernel/kernel.c index cd3e228..64e64ae 100644 --- a/kernel/kernel/kernel.c +++ b/kernel/kernel/kernel.c @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -20,78 +20,78 @@ struct e820_map { void print_e820(struct e820_map *mmap, int mmap_size) { - kprint(" Base | Length | Type | Attrib |\n", 0); - kprint("------------------------------------------------------------\n", 0); + kprint(" Base | Length | Type | Attrib |\n", VGA_LIGHT_GRAY, VGA_BLACK); + kprint("------------------------------------------------------------\n", VGA_LIGHT_GRAY, VGA_BLACK); for (int i=0; ieax, 1); - kprintc(' ', 0); - kprint("EBX: ", 0); + kprintc(' ', VGA_LIGHT_GRAY, VGA_BLACK); + kprint("EBX: ", VGA_LIGHT_GRAY, VGA_BLACK); kprintd(frame->ebx, 1); - kprintc(' ', 0); - kprint("ECX: ", 0); + kprintc(' ', VGA_LIGHT_GRAY, VGA_BLACK); + kprint("ECX: ", VGA_LIGHT_GRAY, VGA_BLACK); kprintd(frame->ecx, 1); - kprintc(' ', 0); - kprint("EDX: ", 0); + kprintc(' ', VGA_LIGHT_GRAY, VGA_BLACK); + kprint("EDX: ", VGA_LIGHT_GRAY, VGA_BLACK); kprintd(frame->edx, 1); - kprintc('\n', 0); - kprint("EBP: ", 0); + kprintc('\n', VGA_LIGHT_GRAY, VGA_BLACK); + kprint("EBP: ", VGA_LIGHT_GRAY, VGA_BLACK); kprintd(frame->ebp, 1); - kprintc(' ', 0); - kprint("ESP: ", 0); + kprintc(' ', VGA_LIGHT_GRAY, VGA_BLACK); + kprint("ESP: ", VGA_LIGHT_GRAY, VGA_BLACK); kprintd(frame->esp, 1); - kprintc('\n', 0); - kprint("ESI: ", 0); + kprintc('\n', VGA_LIGHT_GRAY, VGA_BLACK); + kprint("ESI: ", VGA_LIGHT_GRAY, VGA_BLACK); kprintd(frame->esi, 1); - kprintc(' ', 0); - kprint("EDI: ", 0); + kprintc(' ', VGA_LIGHT_GRAY, VGA_BLACK); + kprint("EDI: ", VGA_LIGHT_GRAY, VGA_BLACK); kprintd(frame->edi, 1); - kprintc('\n', 0); - kprint("EIP: ", 0); + kprintc('\n', VGA_LIGHT_GRAY, VGA_BLACK); + kprint("EIP: ", VGA_LIGHT_GRAY, VGA_BLACK); kprintd(frame->eip, 1); - kprintc(' ', 0); - kprint("EFLAGS: ", 0); + kprintc(' ', VGA_LIGHT_GRAY, VGA_BLACK); + kprint("EFLAGS: ", VGA_LIGHT_GRAY, VGA_BLACK); kprintd(frame->eflags, 1); - kprintc('\n', 0); + kprintc('\n', VGA_LIGHT_GRAY, VGA_BLACK); PANIC("double fault"); } void kmain(struct e820_map *mmap, int mmap_size) { - screen_clear(); - kprint("Welcome to Nameless OS!\nRunning revision: ", 0); - kprint(GIT_COMMIT, 0); - kprint("\n", 0); - kprint("BIOS memory map:\n", 0); + vga_initialize(); + kprint("Welcome to Nameless OS!\nRunning revision: ", VGA_LIGHT_GRAY, VGA_BLACK); + kprint(GIT_COMMIT, VGA_LIGHT_GRAY, VGA_BLACK); + kprint("\n", VGA_LIGHT_GRAY, VGA_BLACK); + kprint("BIOS memory map:\n", VGA_LIGHT_GRAY, VGA_BLACK); print_e820(mmap, mmap_size); - kprint("Preparing IDT...\n", 0); + kprint("Preparing IDT...\n", VGA_LIGHT_GRAY, VGA_BLACK); for (int i=0; i<48; i++) { idt_set_descriptor(idt, i, 0x8, _int_handler_table[i], IDT_INTERRUPT_GATE, 0); } - kprint("IDT prepared, loading...\n", 0); + kprint("IDT prepared, loading...\n", VGA_LIGHT_GRAY, VGA_BLACK); populate_idtr(&idtr, idt); load_idt(idtr); - kprint("Setting up interrupts...\n", 0); + kprint("Setting up interrupts...\n", VGA_LIGHT_GRAY, VGA_BLACK); register_interrupt(8, &double_fault_handler); pic_init(0x20, 0x28); pic_mask_all(); asm volatile ("sti"); - kprint("All done\n", 0); + kprint("All done\n", VGA_LIGHT_GRAY, VGA_BLACK); while(1); } diff --git a/kernel/kernel/kprint.c b/kernel/kernel/kprint.c new file mode 100644 index 0000000..654a0a0 --- /dev/null +++ b/kernel/kernel/kprint.c @@ -0,0 +1,100 @@ +#include +#include + +void tty_initialize() +{ + vga_initialize(); +} + +void kprint(const char *string, const enum vga_color fg, const enum vga_color bg) +{ + char character = *string; + for (int i=1; character; i++) { + vga_print_char(character, fg, bg); + character = string[i]; + } +} + +void kprintc(const char character, const enum vga_color fg, const enum vga_color bg) +{ + vga_print_char(character, fg, bg); +} + +void kprintnibble(uint8_t nibble) +{ + nibble &= 0xf; + if (nibble < 0xa) + kprintc('0' + nibble, VGA_LIGHT_GRAY, VGA_BLACK); + else kprintc('a' - 0xa + nibble, VGA_LIGHT_GRAY, VGA_BLACK); +} + +void kprintb(const uint8_t byte, const int print_delm) +{ + if (print_delm) + kprint("0x", VGA_LIGHT_GRAY, VGA_BLACK); + + kprintnibble(byte >> 4); + kprintnibble(byte); +} + +void kprintw(const uint16_t word, const int print_delm) +{ + if (print_delm) + kprint("0x", VGA_LIGHT_GRAY, VGA_BLACK); + + kprintb(word >> 8, 0); + kprintb(word, 0); +} + +void kprintd(const uint32_t dword, const int print_delm) +{ + if (print_delm) + kprint("0x", VGA_LIGHT_GRAY, VGA_BLACK); + + kprintw(dword >> 16, 0); + kprintw(dword, 0); +} + +void kprintq(const uint64_t qword, const int print_delm) +{ + if (print_delm) + kprint("0x", VGA_LIGHT_GRAY, VGA_BLACK); + + kprintd(qword >> 32, 0); + kprintd(qword, 0); +} + +int kprintdec(uint32_t num, const enum vga_color fg, const enum vga_color bg) +{ + char buffer[11]; + int digits = 10; + /* TODO: make an actual memset function to use instead of this */ + for (int i=0; i<11; i++) { + buffer[i] = 0; + } + + /* put the numbers in the buffer */ + for (int i=9; i>0 && num>0; i--) { + const uint8_t currdigit = num%10; + buffer[i] = currdigit+'0'; + num /= 10; + } + + /* shift the array as much as needed */ + while (*buffer == '\0') { + digits--; + for (int i=0; i<9; i++) { + buffer[i] = buffer[i+1]; + } + } + + /* zero out any leftovers */ + if (digits < 10) { + for (int i=digits; i<10; i++) { + buffer[i] = '\0'; + } + } + + kprint(buffer, fg, bg); + return digits; +} -- 2.39.2