From b619b9ed1d69e28616191f159f28001de3ca65d4 Mon Sep 17 00:00:00 2001 From: AfonsoCMSousa Date: Thu, 20 Nov 2025 22:40:00 +0000 Subject: [PATCH] Feat: Better IO functions & Refractor of "colors.h" to "stdio.h" --- boot/elevator.asm | 10 ++ colors.h | 103 -------------- kernel.c | 43 ++---- stdio.h | 342 ++++++++++++++++++++++++++++++++++++++++++++++ types.h | 92 +++++++++++++ 5 files changed, 456 insertions(+), 134 deletions(-) delete mode 100644 colors.h create mode 100644 stdio.h create mode 100644 types.h diff --git a/boot/elevator.asm b/boot/elevator.asm index 304f0ee..77d31d7 100644 --- a/boot/elevator.asm +++ b/boot/elevator.asm @@ -449,6 +449,16 @@ protected_mode: mov eax, cr4 or eax, 0x20 mov cr4, eax + + ; Enable FXSAVE/FXRSTOR and unmask SSE exceptions + mov eax, cr0 + and ax, 0xFFFB ; clear EM + or ax, 0x0002 ; set MP + mov cr0, eax + + mov eax, cr4 + or ax, 0x0600 ; set OSFXSR | OSXMMEXCPT + mov cr4, eax ; Enable Long Mode mov ecx, 0xC0000080 diff --git a/colors.h b/colors.h deleted file mode 100644 index 3542a35..0000000 --- a/colors.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef COLORS_H -#define COLORS_H - -#define VGA_WIDTH 80 -#define VGA_HEIGHT 25 - -#define VGA_MEMORY_ADDRESS 0xB8000 - -/* IN VGA - Video Memory Arrya: - * short - * 1s byte (left most) -> TEXT COLOR - * 2s byte -> BACK COLOR - * 3rd and 4rt byte -> TEXT (unsigned char) AKA CodePoint - */ - -typedef struct __attribute__((packed)) _VGA { - unsigned char codepoint; // 3rd and 4th byte - unsigned char color; // 1st byte: text color, 2nd byte: background color - // LAST BIT IS BLINKING FLAG -} _VGA; - -typedef enum _VGA_COLOR { - BLACK = 0x0, - BLUE = 0x1, - GREEN = 0x2, - CYAN = 0x3, - RED = 0x4, - MAGENTA = 0x5, - BROWN = 0x6, - LIGHT_GREY = 0x7, - DARK_GREY = 0x8, - LIGHT_BLUE = 0x9, - LIGHT_GREEN = 0xA, - LIGHT_CYAN = 0xB, - LIGHT_RED = 0xC, - LIGHT_MAGENTA = 0xD, - YELLOW = 0xE, - WHITE = 0xF -} _VGA_COLOR; - -typedef struct _VGA_screen_space{ - unsigned int line; - unsigned int column; - -} _VGA_screen_space; - -static _VGA_screen_space cursor_pos = {0, 0}; - -/* - * END OF DECLARATIONS - */ - -/* - * START OF FUNCTIONS - */ - -// Convert _VGA_COLOR to color byte -static inline unsigned char __vga_color_byte(_VGA_COLOR fg, _VGA_COLOR bg, int blink) { - unsigned char color = (bg << 4) | fg; - if (blink) { - color |= 0x80; // Set the blinking BIT - // to the highest bit - } - return color; -} - -// Get pointer to VGA memory -static inline volatile _VGA* __vga_memory() { - return (volatile _VGA*)VGA_MEMORY_ADDRESS; -} - -static inline void __clear_screen() { - volatile _VGA* vga = __vga_memory(); - for (int i = 0; i < VGA_WIDTH * VGA_HEIGHT; i++) { - vga[i].codepoint = ' '; - vga[i].color = __vga_color_byte(WHITE, BLACK, 0); - } -} - -static inline int __put_char_VGA_POS(_VGA _c, _VGA_screen_space _position, int _blink) { - if(_position.line > VGA_HEIGHT || _position.column > VGA_WIDTH) return 0; - - volatile _VGA* vga = __vga_memory(); - - vga[(_position.line * VGA_WIDTH) + _position.column].codepoint = _c.codepoint; - vga[(_position.line * VGA_WIDTH) + _position.column].color = _c.color; - - return 1; -} - -static inline int __put_char(int column, int line, unsigned codepoint, _VGA_COLOR foreground, _VGA_COLOR background, int _blink) { - _VGA __temp_vga; - __temp_vga.color = __vga_color_byte(foreground, background, _blink); - __temp_vga.codepoint = codepoint; - - _VGA_screen_space __temp_vga_space; - __temp_vga_space.column = column; - __temp_vga_space.line = line; - - return __put_char_VGA_POS(__temp_vga, __temp_vga_space, _blink); -} - -#endif diff --git a/kernel.c b/kernel.c index e582cbb..72d588c 100644 --- a/kernel.c +++ b/kernel.c @@ -6,45 +6,26 @@ // 0xB0000 for monochrome text mode (32 KB) // 0xB8000 for color text mode and CGA-compatible graphics modes (32 KB) -#include "colors.h" +#include "stdio.h" - -/* -static void __put_char(char c, unsigned char color) { - volatile unsigned short *vga = (volatile unsigned short *)0xB8000; - - static int line = 0; - static int column = 2; - - if (line >= 16) { - column += 3; - line = 0; - } - - line++; - - vga[line * 80 + 0 + column] = (0x2F << 8) | line; // White color - vga[line * 80 + 1 + column] = (color << 8) | c; // White color -} -*/ +typedef struct user { + int id; + const char *name; +} user; void kmain(void) { __clear_screen(); - _VGA Char; - Char.codepoint = 'T'; - Char.color = (WHITE << 4) | BLACK; + user current_user; + current_user.id = 1; + current_user.name = "admin"; - _VGA_screen_space Space; - Space.column = 2; - Space.line = 7; + printf("SoraOS Kernel Initialized!\n"); - __put_char_VGA_POS(Char, Space, 1); + printf("\tUser name:\t%s\n", current_user.name); + printf("\tUser id:\t%d\n", current_user.id); - Space.line = 4; - Space.column = 3; - - __put_char_VGA_POS(Char, Space, 0); + vga_set_cursor(0, 0); // Infinite loop while (1) { diff --git a/stdio.h b/stdio.h new file mode 100644 index 0000000..2f5c371 --- /dev/null +++ b/stdio.h @@ -0,0 +1,342 @@ +#ifndef COLORS_H +#define COLORS_H + +#include "types.h" +#include +#include + +#define VGA_WIDTH 80 +#define VGA_HEIGHT 25 + +#define VGA_MEMORY_ADDRESS 0xB8000 + +/* IN VGA - Video Memory Arrya: + * short + * 1s byte (left most) -> TEXT COLOR + * 2s byte -> BACK COLOR + * 3rd and 4rt byte -> TEXT (unsigned char) AKA CodePoint + */ + +typedef struct __attribute__((packed)) _VGA { + unsigned char codepoint; // 3rd and 4th byte + unsigned char color; // 1st byte: text color, 2nd byte: background color + // LAST BIT IS BLINKING FLAG +} _VGA; + +typedef enum _VGA_COLOR { + BLACK = 0x0, + BLUE = 0x1, + GREEN = 0x2, + CYAN = 0x3, + RED = 0x4, + MAGENTA = 0x5, + BROWN = 0x6, + LIGHT_GREY = 0x7, + DARK_GREY = 0x8, + LIGHT_BLUE = 0x9, + LIGHT_GREEN = 0xA, + LIGHT_CYAN = 0xB, + LIGHT_RED = 0xC, + LIGHT_MAGENTA = 0xD, + YELLOW = 0xE, + WHITE = 0xF +} _VGA_COLOR; + +typedef struct _VGA_screen_space { + unsigned int line; + unsigned int column; + +} _VGA_screen_space; + +static _VGA_screen_space cursor_pos = {0, 0}; +static _VGA_screen_space text_pos = {0, 0}; + +static unsigned int tab_pos = 0; + +#define DEFAULT_BG BLUE +#define DEFAULT_FG WHITE + +/* + * END OF DECLARATIONS + */ + + + +/* + * START OF OUTPUT FUNCTIONS + */ + +int printf(const char *fmt, ...); + +// Convert _VGA_COLOR to color byte +static inline unsigned char __vga_color_byte(_VGA_COLOR fg, _VGA_COLOR bg, int blink) { + unsigned char color = (bg << 4) | fg; + if (blink) { + color |= 0x80; // Set the blinking BIT + // to the highest bit + } + return color; +} + +// Get pointer to VGA memory +static inline volatile _VGA *__vga_memory() { + return (volatile _VGA *)VGA_MEMORY_ADDRESS; +} + +static inline void __clear_screen() { + volatile _VGA *vga = __vga_memory(); + for (int i = 0; i < VGA_WIDTH * VGA_HEIGHT; i++) { + vga[i].codepoint = ' '; + vga[i].color = __vga_color_byte(DEFAULT_FG, DEFAULT_BG, 0); + } +} + +static inline void __clear_screen_colored(_VGA_COLOR background) { + volatile _VGA *vga = __vga_memory(); + for (int i = 0; i < VGA_WIDTH * VGA_HEIGHT; i++) { + vga[i].codepoint = ' '; + vga[i].color = __vga_color_byte(WHITE, background, 0); + } +} + +static inline int __put_char_VGA_POS(_VGA _c, _VGA_screen_space _position, int _blink) { + if (_position.line > VGA_HEIGHT || _position.column > VGA_WIDTH) + return 0; + + volatile _VGA *vga = __vga_memory(); + + if (_c.codepoint == '\n') { + text_pos.line++; + text_pos.column = 0; + return 1; + } + + if (_c.codepoint == '\t') { + int spaces = 4 - (_position.column % 4); + if (spaces == 0) + spaces = 4; + + int written = 0; + while (spaces--) { + if (_position.column >= VGA_WIDTH) { + _position.column = 0; + _position.line++; + if (_position.line >= VGA_HEIGHT) { + // TODO: scroll or wrap + break; + } + } + + vga[(_position.line * VGA_WIDTH) + _position.column].codepoint = ' '; + vga[(_position.line * VGA_WIDTH) + _position.column].color = _c.color; + _position.column++; + written++; + } + + text_pos.line = _position.line; + text_pos.column = _position.column; + + return written; + } + + vga[(_position.line * VGA_WIDTH) + _position.column].codepoint = _c.codepoint; + vga[(_position.line * VGA_WIDTH) + _position.column].color = _c.color; + + return 1; +} + +static inline int __put_char(int column, int line, unsigned codepoint, _VGA_COLOR foreground, _VGA_COLOR background, int _blink) { + _VGA __temp_vga; + __temp_vga.color = __vga_color_byte(foreground, background, _blink); + __temp_vga.codepoint = codepoint; + + _VGA_screen_space __temp_vga_space; + __temp_vga_space.column = column; + __temp_vga_space.line = line; + + return __put_char_VGA_POS(__temp_vga, __temp_vga_space, _blink); +} + +static inline int __put_string(int column, int line, const char *__args, _VGA_COLOR foreground, _VGA_COLOR background, int _blink) { + unsigned long _counter = 0; + + while (*__args != '\0') { + + if (column >= VGA_WIDTH) { + column = 0; + line++; + + if (line >= VGA_HEIGHT) { + // TODO: SCROLL OR LOOP... + } + } + + _counter += __put_char(column++, line, *__args++, foreground, background, _blink); + } + + return _counter; +} + +static inline int __print_string(const char *__args, _VGA_COLOR foreground, _VGA_COLOR background, int _blink) { + unsigned long _counter = 0; + + while (*__args != '\0') { + + if (text_pos.column >= VGA_WIDTH) { + text_pos.column = 0; + text_pos.line++; + + if (text_pos.line >= VGA_HEIGHT) { + // TODO: SCROLL OR LOOP... + } + } + + _counter += __put_char(text_pos.column++, text_pos.line, *__args++, foreground, background, _blink); + } + + return _counter; +} + +// TODO: Implement later on the (argc, ...) to allow for stuff like printf("%d", number); +static inline int printf_s(const char *args) { + // by defeault we dont blink lol + return __print_string(args, DEFAULT_FG, DEFAULT_BG, 0); +} + +static int __printf_internal(const char *fmt, va_list args) { + int count = 0; + + while (*fmt) { + if (*fmt != '%') { + __put_char(text_pos.column++, text_pos.line, *fmt++, DEFAULT_FG, DEFAULT_BG, 0); + count++; + continue; + } + + fmt++; // skip % + + switch (*fmt) { + case 'c': { + char c = (char)va_arg(args, int); + __put_char(text_pos.column++, text_pos.line, c, DEFAULT_FG, DEFAULT_BG, 0); + count++; + break; + } + + case 's': { + const char *s = va_arg(args, const char *); + count += __print_string(s, DEFAULT_FG, DEFAULT_BG, 0); + break; + } + + case 'd': { + int n = va_arg(args, int); + char buf[32]; + count += __print_string(itoa(n, buf), DEFAULT_FG, DEFAULT_BG, 0); + break; + } + + case 'u': { + unsigned n = va_arg(args, unsigned); + char buf[32]; + count += __print_string(utoa(n, buf), DEFAULT_FG, DEFAULT_BG, 0); + break; + } + + case 'o': { + unsigned n = va_arg(args, unsigned); + char buf[32]; + count += __print_string(otoa(n, buf), DEFAULT_FG, DEFAULT_BG, 0); + break; + } + + case 'x': { + unsigned n = va_arg(args, unsigned); + char buf[32]; + count += __print_string(__utoa(n, buf, 16), DEFAULT_FG, DEFAULT_BG, 0); + break; + } + + /* + * TODO: Enable floating point support later + * This requires enabling FPU in the kernel + case 'f': { + double f = va_arg(args, double); + char buf[64]; + count += __print_string(ftoa(f, buf), DEFAULT_FG, DEFAULT_BG, 0); + break; + } + */ + + case '%': { + __put_char(text_pos.column++, text_pos.line, '%', DEFAULT_FG, DEFAULT_BG, 0); + count++; + break; + } + + default: + __put_char(text_pos.column++, text_pos.line, *fmt, DEFAULT_FG, DEFAULT_BG, 0); + count++; + break; + } + + fmt++; + } + + return count; +} + +int printf(const char *fmt, ...) { + va_list args; + va_start(args, fmt); + int result = __printf_internal(fmt, args); + va_end(args); + return result; +} + +/* + * END OF OUTPUT FUNCTIONS + */ + + + + +/* + * START OF INPUT FUNCTIONS + */ + +static inline void outb(unsigned short port, unsigned char val) { + __asm__ volatile ("outb %0, %1" : : "a"(val), "Nd"(port)); +} + +static inline void __VGA_set_cursor(unsigned int column, unsigned int line) { + if (column >= VGA_WIDTH) column = VGA_WIDTH - 1; + if (line >= VGA_HEIGHT) line = VGA_HEIGHT - 1; + + unsigned short pos = line * VGA_WIDTH + column; + + // Send high byte + outb(0x3D4, 0x0E); + outb(0x3D5, (pos >> 8) & 0xFF); + + // Send low byte + outb(0x3D4, 0x0F); + outb(0x3D5, pos & 0xFF); + + cursor_pos.column = column; + cursor_pos.line = line; + + text_pos.column = column; + text_pos.line = line; +} + +static inline void __VGA_set_cursor_VGA_pos(_VGA_screen_space pos) { + __VGA_set_cursor(pos.column, pos.line); +} + +static inline _VGA_screen_space get_cursor_pos() { + _VGA_screen_space __temp = {cursor_pos.column, cursor_pos.line}; + return __temp; +} + +#endif diff --git a/types.h b/types.h new file mode 100644 index 0000000..9caffa8 --- /dev/null +++ b/types.h @@ -0,0 +1,92 @@ +#ifndef TYPES_H +#define TYPES_H + +#include + +static char* __itoa(int value, char* buffer, int base) { + char* ptr = buffer, *ptr1 = buffer, tmp_char; + int tmp_value; + + if (value < 0 && base == 10) { + value = -value; + *ptr++ = '-'; + ptr1++; + } + + do { + tmp_value = value; + value /= base; + *ptr++ = "0123456789ABCDEF"[tmp_value - value * base]; + } while (value); + + *ptr-- = '\0'; + + while (ptr1 < ptr) { + tmp_char = *ptr; + *ptr-- = *ptr1; + *ptr1++ = tmp_char; + } + + return buffer; +} + +static char* __utoa(unsigned int value, char* buffer, int base) { + char* ptr = buffer, *ptr1 = buffer, tmp_char; + unsigned int tmp_value; + + do { + tmp_value = value; + value /= base; + *ptr++ = "0123456789ABCDEF"[tmp_value - value * base]; + } while (value); + + *ptr-- = '\0'; + + while (ptr1 < ptr) { + tmp_char = *ptr; + *ptr-- = *ptr1; + *ptr1++ = tmp_char; + } + + return buffer; +} + +static char* __ftoa(double value, char* buffer) { + int int_part = (int)value; + double frac_part = value - (double)int_part; + char* ptr = __itoa(int_part, buffer, 10); + + *ptr++ = '.'; + + for (int i = 0; i < 6; i++) { + frac_part *= 10.0; + int digit = (int)frac_part; + *ptr++ = '0' + digit; + frac_part -= (double)digit; + } + + *ptr = '\0'; + return buffer; +} + +static char* itoa(int value, char* buffer) { + return __itoa(value, buffer, 10); +} + +static char* utoa(unsigned int value, char* buffer) { + return __utoa(value, buffer, 10); +} + +static char* otoa(unsigned int value, char* buffer) { + return __utoa(value, buffer, 8); +} + +static char* xtoa(unsigned int value, char* buffer) { + return __utoa(value, buffer, 16); +} + +static char* ftoa(double value, char* buffer) { + return __ftoa(value, buffer); +} + +#endif // TYPES_H