From 2160a41e818bf23dfcedf6465705f7932009eec6 Mon Sep 17 00:00:00 2001 From: Arnau478 Date: Fri, 17 Jun 2022 17:13:55 +0200 Subject: [PATCH] Finished VGA driver and implemented stdio.h (printf and puts) --- src/kernel/drivers/vga.c | 24 +++++----- src/kernel/drivers/vga.h | 14 +++--- src/kernel/main.c | 4 +- src/kernel/stdio.c | 101 ++++++++++++++++++++++++++++++++++++++- src/kernel/stdio.h | 2 + 5 files changed, 123 insertions(+), 22 deletions(-) diff --git a/src/kernel/drivers/vga.c b/src/kernel/drivers/vga.c index 41a9e23..82ed3cb 100644 --- a/src/kernel/drivers/vga.c +++ b/src/kernel/drivers/vga.c @@ -3,22 +3,22 @@ static uint8_t current_color = VGA_COLOR_DEFAULT; -void set_char(int x, int y, char c){ +void vga_set_char(int x, int y, char c){ VGA_MEMORY[(x+y*VGA_WIDTH)*2] = c; } -void set_color(int x, int y, uint8_t color){ +void vga_set_color(int x, int y, uint8_t color){ VGA_MEMORY[(x+y*VGA_WIDTH)*2+1] = color; } -void set_cursor(int offset){ +void vga_set_cursor(int offset){ i686_outb(VGA_PORT_CTRL, 14); i686_outb(VGA_PORT_DATA, (uint8_t)(offset >> 8)); i686_outb(VGA_PORT_CTRL, 15); i686_outb(VGA_PORT_DATA, (uint8_t)(offset & 0xff)); } -int get_cursor(){ +int vga_get_cursor(){ i686_outb(VGA_PORT_CTRL, 14); int offset = i686_inb(VGA_PORT_DATA) << 8; // High byte i686_outb(VGA_PORT_CTRL, 15); @@ -34,7 +34,7 @@ static int get_offset_x(int offset){ return (offset - (get_offset_y(offset)*VGA_WIDTH)); } -int print_char(char c, int x, int y){ +int vga_print_char(char c, int x, int y){ if(x >= VGA_WIDTH || y >= VGA_HEIGHT){ // Incorrect coords VGA_MEMORY[2*VGA_WIDTH*VGA_HEIGHT-2] = 'E'; VGA_MEMORY[2*VGA_WIDTH*VGA_HEIGHT-1] = VGA_COLOR_BG_RED || VGA_COLOR_FG_BLACK; @@ -43,7 +43,7 @@ int print_char(char c, int x, int y){ int offset; if(x >= 0 && y >= 0) offset = y*VGA_WIDTH+x; - else offset = get_cursor(); + else offset = vga_get_cursor(); if(c == '\n'){ y = get_offset_y(offset); @@ -61,17 +61,17 @@ int print_char(char c, int x, int y){ // TODO: Scroll - set_cursor(offset); + vga_set_cursor(offset); return offset; } -void puts_at(char *str, int x, int y){ +void vga_print_string_at(char *str, int x, int y){ int offset; if(x >= 0 && y >= 0){ offset = y*VGA_WIDTH+x; } else{ - offset = get_cursor(); + offset = vga_get_cursor(); x = get_offset_x(offset); y = get_offset_y(offset); } @@ -105,13 +105,13 @@ void puts_at(char *str, int x, int y){ } } else{ - offset = print_char(*(str++), x, y); + offset = vga_print_char(*(str++), x, y); x = get_offset_x(offset); y = get_offset_y(offset); } } } -void puts(char *str){ - puts_at(str, -1, -1); +void vga_print_string(char *str){ + vga_print_string_at(str, -1, -1); } diff --git a/src/kernel/drivers/vga.h b/src/kernel/drivers/vga.h index a24494f..700140a 100644 --- a/src/kernel/drivers/vga.h +++ b/src/kernel/drivers/vga.h @@ -46,10 +46,10 @@ #define VGA_PORT_CTRL 0x3D4 #define VGA_PORT_DATA 0x3D5 -void set_char(int x, int y, char c); -void set_color(int x, int y, uint8_t color); -void set_cursor(int offset); -int get_cursor(); -int print_char(char c, int x, int y); -void puts_at(char *str, int x, int y); -void puts(char *str); +void vga_set_char(int x, int y, char c); +void vga_set_color(int x, int y, uint8_t color); +void vga_set_cursor(int offset); +int vga_get_cursor(); +int vga_print_char(char c, int x, int y); +void vga_print_string_at(char *str, int x, int y); +void vga_print_string(char *str); diff --git a/src/kernel/main.c b/src/kernel/main.c index 94cc39b..f61db0d 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -2,6 +2,8 @@ #include "stdio.h" void __attribute__((cdecl)) kmain(uint64_t magic, uint64_t addr){ - printf("Hello world!\n\x1b[32m:D\x1b[0m\n"); + puts("\x1b[33mWARNING\x1b[0m"); + printf(": amazing %s ahead!\n", "math"); + printf("%i+%i=%i\n", 1, 1, 2); for(;;); // Halt here } diff --git a/src/kernel/stdio.c b/src/kernel/stdio.c index a637c2d..315f91e 100644 --- a/src/kernel/stdio.c +++ b/src/kernel/stdio.c @@ -1,6 +1,103 @@ +#include +#include #include "stdio.h" #include "drivers/vga.h" -void printf(char *fmt, ...){ - puts(fmt); +static char g_HexChars[] = "0123456789abcdef"; + +void puts(char *str){ + vga_print_string(str); +} + +void putc(char c){ + char str[2]; + str[0] = c; + str[1] = '\0'; + vga_print_string(str); +} + +static void printf_signed(unsigned long long num, int radix){ + char buffer[32]; + int pos = 0; + + // Convert to ASCII + do{ + unsigned long long rem = num % radix; + num /= radix; + buffer[pos++] = g_HexChars[rem]; + } while(num > 0); + + while(--pos >= 0) putc(buffer[pos]); // Note reverse order +} + +static void printf_unsigned(unsigned long long num, int radix){ + if(num < 0){ + putc('-'); + printf_unsigned(-num, radix); + } + else printf_unsigned(num, radix); +} + +void printf(char *fmt, ...){ + // Variadic function arguments + va_list args; + va_start(args, fmt); + + while(*fmt){ + if(*fmt == '%'){ + bool number = false; + bool sign = false; + int radix = 10; + + fmt++; + switch(*fmt){ + case '%': + putc('%'); + break; + case 'c': + putc((char)va_arg(args, int)); + break; + case 's': + puts(va_arg(args, char *)); + break; + case 'd': + case 'i': + number = true; + radix = 10; + sign = true; + break; + case 'u': + number = true; + radix = 10; + sign = false; + break; + case 'X': + case 'x': + case 'p': + number = true; + radix = 16; + sign = false; + break; + case 'o': + number = true; + radix = 8; + sign = false; + break; + default: break; + } + + // TODO: Implement length modifiers + if(number){ + if(sign){ + printf_signed(va_arg(args, int), radix); + } + else{ + printf_unsigned(va_arg(args, unsigned int), radix); + } + } + + fmt++; + } + else putc(*(fmt++)); + } } diff --git a/src/kernel/stdio.h b/src/kernel/stdio.h index 830ff0f..8f0a6ae 100644 --- a/src/kernel/stdio.h +++ b/src/kernel/stdio.h @@ -1,3 +1,5 @@ #pragma once +void puts(char *str); +void putc(char c); void printf(char *fmt, ...);