]> git.dujemihanovic.xyz Git - nameless-os.git/commitdiff
kernel: Huge refactoring of tty driver
authorDuje Mihanović <duje.mihanovic@skole.hr>
Sat, 2 Jul 2022 12:54:37 +0000 (14:54 +0200)
committerDuje Mihanović <duje.mihanovic@skole.hr>
Sat, 2 Jul 2022 12:54:37 +0000 (14:54 +0200)
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

12 files changed:
kernel/arch/x86/Makefile
kernel/arch/x86/irq/interrupt.c
kernel/arch/x86/tty.c [new file with mode: 0644]
kernel/arch/x86/tty/Makefile [deleted file]
kernel/arch/x86/tty/tty.c [deleted file]
kernel/include/arch/x86/tty.h [new file with mode: 0644]
kernel/include/kprint.h [new file with mode: 0644]
kernel/include/panic.h
kernel/include/tty.h [deleted file]
kernel/kernel/Makefile
kernel/kernel/kernel.c
kernel/kernel/kprint.c [new file with mode: 0644]

index b164c9d17c4cfbc309f12e05215bae428b7e26a9..c15bef91711b8f9a78e85ed5a232c390739d4bb1 100644 (file)
@@ -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)
index 5c448fece1937c7da813687b8c4d9eb1addcd29b..b3c31735af156cba8e01422cb03969f933bea41e 100644 (file)
@@ -1,6 +1,6 @@
 #include <irq/idt.h>
 #include <irq/interrupt.h>
-#include <tty.h>
+#include <kprint.h>
 #include <stddef.h>
 #include <irq/i8259a.h>
 
@@ -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 (file)
index 0000000..6796594
--- /dev/null
@@ -0,0 +1,94 @@
+#include <io.h>
+#include <tty.h>
+#include <stdint.h>
+
+#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<VGA_HEIGHT; y++) {
+               for (int x = 0; x<VGA_WIDTH; x++) {
+                       *vga_get_memory_address(x, y-1) = *vga_get_memory_address(x, y);
+               }
+       }
+
+       for (int x = 0; x<VGA_WIDTH; x++) {
+               *vga_get_memory_address(x, VGA_HEIGHT-1) = vga_get_char(VGA_LIGHT_GRAY, VGA_BLACK, ' ');
+       }
+       cursor_y = VGA_HEIGHT - 1;
+}
+
+static void vga_set_cursor(int x, int y)
+{
+       uint16_t cursor_address = y*VGA_WIDTH + x;
+
+       outb(crtc_port, 0xe);
+       outb(crtc_port+1, cursor_address>>8);
+       outb(crtc_port, 0xf);
+       outb(crtc_port+1, cursor_address);
+}
+
+static void vga_screen_clear(void)
+{
+       for (int y=0; y<VGA_HEIGHT; y++) {
+               for (int x=0; x<VGA_WIDTH; x++) {
+                       *vga_get_memory_address(x, y) = vga_get_char(VGA_LIGHT_GRAY, VGA_BLACK, ' ');
+               }
+       }
+
+       cursor_x = 0;
+       cursor_y = 0;
+       vga_set_cursor(0, 0);
+}
+
+void vga_print_char(const char character, const enum vga_color fg, const enum vga_color bg)
+{
+       if (character == '\n') {
+               cursor_x = 0;
+               cursor_y++;
+       } else {
+               *vga_get_memory_address(cursor_x, cursor_y) = vga_get_char(fg, bg, character);
+               cursor_x++;
+       }
+
+       if (cursor_x >= 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 (file)
index 0498223..0000000
+++ /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 (file)
index ca3212a..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-#include <io.h>
-#include <tty.h>
-#include <stdint.h>
-
-#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 (file)
index 0000000..a7cb8cf
--- /dev/null
@@ -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 (file)
index 0000000..b883c14
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef KPRINT_H
+#define KPRINT_H
+
+#include <stdint.h>
+#include <tty.h>
+
+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
index f481e0cd0a4a745f7520d5b4430336cce8c641f6..5c4d662db6a09dada0aa92861514f1b32aa40b45 100644 (file)
@@ -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 (file)
index 87aad81..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef TTY_H
-#define TTY_H
-
-#include <stdint.h>
-
-#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
index 871687559999a2655220b55d1c30f9f685e283a6..1827b7250e174e9d68704c402e418b8c1b1246e4 100644 (file)
@@ -1 +1 @@
-KERNEL_OBJ += kernel/kernel.o
+KERNEL_OBJ += $(addprefix kernel/, kernel.o kprint.o)
index cd3e228a0867ddf370fdabd48acdd6c9af223cf8..64e64ae45b01f0c805018aa51bac6bb868439a39 100644 (file)
@@ -1,4 +1,4 @@
-#include <tty.h>
+#include <kprint.h>
 #include <io.h>
 #include <irq/idt.h>
 #include <irq/interrupt.h>
@@ -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; i<mmap_size; i++) {
                kprintq(mmap[i].base, 1);
-               kprintc('|', 0);
+               kprintc('|', VGA_LIGHT_GRAY, VGA_BLACK);
                kprintq(mmap[i].length, 1);
-               kprintc('|', 0);
+               kprintc('|', VGA_LIGHT_GRAY, VGA_BLACK);
                kprintd(mmap[i].type, 1);
-               kprintc('|', 0);
+               kprintc('|', VGA_LIGHT_GRAY, VGA_BLACK);
                kprintd(mmap[i].attrib, 1);
-               kprintc('|', 0);
-               kprintc('\n', 0);
+               kprintc('|', VGA_LIGHT_GRAY, VGA_BLACK);
+               kprintc('\n', VGA_LIGHT_GRAY, VGA_BLACK);
        }
 }
 
 /* Small handler for double faults. Will be put elsewhere eventually. */
 int double_fault_handler(struct interrupt_frame *frame)
 {
-       kprint("Double fault occurred!\n", VGA_COLOR_BRIGHT_RED);
-       kprint("EAX: ", 0);
+       kprint("Double fault occurred!\n", VGA_BRIGHT_RED, VGA_BLACK);
+       kprint("EAX: ", VGA_LIGHT_GRAY, VGA_BLACK);
        kprintd(frame->eax, 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 (file)
index 0000000..654a0a0
--- /dev/null
@@ -0,0 +1,100 @@
+#include <stdint.h>
+#include <kprint.h>
+
+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;
+}