diff --git a/include/io.h b/include/io.h new file mode 100644 index 0000000..a58a26e --- /dev/null +++ b/include/io.h @@ -0,0 +1,18 @@ +/* io.h +* In/Out +* +* Common library for handling user i/o. Aims to be mechanic agnostic, and instead +* focus on implementing generic functions to format and manipulate data. +*/ +#ifndef IO_H +#define IO_H +#include + +int putc(int (*)(char), char); +int print(int (*)(char), const char*); +int println(int (*)(char), const char*); +int printhex(int (*)(char), uint32_t); +int prindec(int (*)(char), uint32_t out); +int printf(int (*)(char), const char* fmt, ...); + +#endif diff --git a/include/kio.h b/include/vga.h similarity index 64% rename from include/kio.h rename to include/vga.h index c5ad053..198a226 100644 --- a/include/kio.h +++ b/include/vga.h @@ -1,10 +1,10 @@ -/* kio.h - * Kernel I/O +/* vga.h + * VGA * - * Responsible for kernel related in/output, such as VGA and serial + * Responsible for VGA buffer control. */ -#ifndef KIO_H -#define KIO_H +#ifndef VGA_H +#define VGA_H #define VGA_GRID_COLS 80 #define VGA_GRID_ROWS 25 #include @@ -31,12 +31,10 @@ extern uint16_t vga_attributes; // Black background, White foreground //Clear the VGA buffer void vga_clear(); //Put a character in the VGA buffer and move the cursor to the right by one -void vga_putc(char c); void vga_set_attributes(uint8_t attributes); -void vga_print(const char* out); -void vga_println(const char* out); -void vga_printhex(uint32_t out); -void vga_prindec(uint32_t out); -void vga_printf(const char* fmt, ...); +//Write character c to cursor +//Implements IO generic ASCII output +int vga_out(char c); + #endif diff --git a/src/interrupt_handlers.c b/src/interrupt_handlers.c index 362f5a5..c928384 100644 --- a/src/interrupt_handlers.c +++ b/src/interrupt_handlers.c @@ -1,21 +1,26 @@ #include "interrupt_handlers.h" -#include "kio.h" - +#include "vga.h" +#include "io.h" void generic_isr_handler(StateSnapshot_t* cpu_state) { //We made it to C for our interrupt! For now, let's just print our interrupt to the screen. - vga_clear(); - vga_printf("INTERRUPT TRIGGERED! Info below.\n"); - vga_printf("Int_ID|ERR: %X|%X\n", cpu_state->interrupt_id, cpu_state->error_code); - vga_printf("EFLAGS|CS|EIP: %X|%X|%X\n", cpu_state->eflags, cpu_state->cs,cpu_state->eip); - vga_printf("GP Registers:\neax:%X\nebx:%X\necx:%X\nedx:%X\nesp:%X\nebp:%X\nesi:%X\nedi:%X\n", - cpu_state->eax, - cpu_state->ebx, - cpu_state->ecx, - cpu_state->edx, - cpu_state->esp, - cpu_state->ebp, - cpu_state->esi, - cpu_state->edi); - vga_printf("HALT!"); - while(1); + switch(cpu_state->interrupt_id) { + + + default: + vga_clear(); + printf(vga_out, "INTERRUPT TRIGGERED! Info below.\n"); + printf(vga_out, "Int_ID|ERR: %X|%X\n", cpu_state->interrupt_id, cpu_state->error_code); + printf(vga_out, "EFLAGS|CS|EIP: %X|%X|%X\n", cpu_state->eflags, cpu_state->cs,cpu_state->eip); + printf(vga_out, "GP Registers:\neax:%X\nebx:%X\necx:%X\nedx:%X\nesp:%X\nebp:%X\nesi:%X\nedi:%X\n", + cpu_state->eax, + cpu_state->ebx, + cpu_state->ecx, + cpu_state->edx, + cpu_state->esp, + cpu_state->ebp, + cpu_state->esi, + cpu_state->edi); + printf(vga_out, "HALT!"); + while(1); + } } diff --git a/src/io.c b/src/io.c new file mode 100644 index 0000000..8cb32cd --- /dev/null +++ b/src/io.c @@ -0,0 +1,75 @@ +#include "io.h" +#include "kttools.h" +#include + +int printhex(int (*sendDataFnc)(char), uint32_t out) { + char buff[9]; + i_to_str(out, buff, 9, 0x10); + return print(sendDataFnc, buff); +} + +int printdec(int (*sendDataFnc)(char), uint32_t out) { + char buff[11]; + i_to_str(out, buff, 11, 10); + return print(sendDataFnc, buff); +} + +int putc(int (*sendDataFnc)(char), char out) { + return sendDataFnc(out); +} + +int print(int (*sendDataFnc)(char), const char* out) { + int ret = 0; + for (int i = 0; out[i] != '\0' && !ret; i++) + ret = putc(sendDataFnc, out[i]); + return ret; +} + +int println(int (*sendDataFnc)(char), const char* out) { + int ret = print(sendDataFnc, out); + if(ret) + return ret; + ret = print(sendDataFnc, "\n"); + return ret; +} + +/** + * @brief Print a format string to the outstream function. + * + * Print some format string to the output given in sendDataFnc. Supports a few format strings in C format. + * + * @param fmt: The format string to print + * @param ...: Values for the format specifiers + * + * @return No return value + * + */ + +int printf(int (*sendDataFnc)(char), const char* fmt, ...) { + va_list args; + va_start(args, fmt); + int ret = 0; + while(*fmt) { + if(*fmt == '%') { + fmt++; + switch(*fmt) { + case 'X': + ret = print(sendDataFnc, "0x"); + case 'x': + ret = printhex(sendDataFnc, va_arg(args,uint32_t)); + break; + case 'd': + ret = printdec(sendDataFnc, va_arg(args,uint32_t)); + break; + + } + } else { + sendDataFnc(*fmt); + } + fmt++; + if(ret) + return ret; + } + return 0; + +} diff --git a/src/main.c b/src/main.c index 28dfd22..38c3df1 100644 --- a/src/main.c +++ b/src/main.c @@ -1,7 +1,8 @@ //Our own code, at this point... //#include #include -#include "kio.h" +#include "vga.h" +#include "io.h" #include "kttools.h" #include "kmultiboot.h" #include "idt.h" @@ -12,22 +13,21 @@ void kern_main(uint32_t multiboot_magic, mb_info_t* multiboot_info) //First interrupts. setup_idt(); - //wipe the screen vga_clear(); //We're going to use this buffer as our 8char hex representation for reading mem - vga_printf("Entry eax:%X\n", multiboot_magic); + printf(vga_out, "Entry eax:%X\n", multiboot_magic); if(multiboot_magic != 0x2BADB002) { - vga_println("Bootloader not multiboot1 compliant! Needed for mmap, etc. Can't work without it, kthxbye!"); + println(vga_out, "Bootloader not multiboot1 compliant! Needed for mmap, etc. Can't work without it, kthxbye!"); return; } else { - vga_println("Multiboot detected! Continuing..."); + println(vga_out, "Multiboot detected! Continuing..."); } - vga_printf("MEM_LOWER:%X\n", multiboot_info->mem_lower); - vga_printf("MEM_UPPER:%X\n", multiboot_info->mem_upper); + printf(vga_out, "MEM_LOWER:%X\n", multiboot_info->mem_lower); + printf(vga_out, "MEM_UPPER:%X\n", multiboot_info->mem_upper); } diff --git a/src/kio.c b/src/vga.c similarity index 50% rename from src/kio.c rename to src/vga.c index 24fa2a0..22cf66c 100644 --- a/src/kio.c +++ b/src/vga.c @@ -1,4 +1,4 @@ -#include "kio.h" +#include "vga.h" #include "kttools.h" #include @@ -30,20 +30,21 @@ void vga_clear() { } } -void vga_putc(char c) +int vga_out(char c) { //Check for some freaky escape character first if(c == '\n') { cursor_col = 0; //mod implements wraparound cursor_row = (cursor_row + 1) % (VGA_GRID_ROWS-1); - return; + return 0; } //Calculate where in the vga buffer to put the character const size_t index = (VGA_GRID_COLS * cursor_row) + cursor_col; //VGA buffer cell consists of the first half attributes, second half character vga_buffer[index] = vga_attributes | c; cursor_col++; + return 0; } void vga_set_attributes(uint8_t attributes) { @@ -51,61 +52,9 @@ void vga_set_attributes(uint8_t attributes) { } -void vga_print(const char* out) { - for (int i = 0; out[i] != '\0'; i++) - vga_putc(out[i]); -} -void vga_println(const char* out) { - vga_print(out); - vga_print("\n"); -} -void vga_printhex(uint32_t out) { - char buff[9]; - i_to_str(out, buff, 9, 0x10); - vga_print(buff); -} -void vga_printdec(uint32_t out) { - char buff[11]; - i_to_str(out, buff, 11, 10); - vga_print(buff); -} -/** - * @brief Print a format string to the VGA output. - * - * Print some format string to the vga output cleanly. Supports a few format strings in C format. - * - * @param fmt: The format string to print - * @param ...: Values for the format specifiers - * - * @return No return value - * - */ -void vga_printf(const char* fmt, ...) { - va_list args; - va_start(args, fmt); - while(*fmt) { - if(*fmt == '%') { - fmt++; - switch(*fmt) { - case 'X': - vga_print("0x"); - case 'x': - vga_printhex(va_arg(args,uint32_t)); - break; - case 'd': - vga_printdec(va_arg(args,uint32_t)); - break; - } - } else { - vga_putc(*fmt); - } - fmt++; - } - -}