#include #include #include #include #include #include #include "../include/kprint.h" #include "../drivers/serial.h" #include "../hal/tsc.h" #define FORMAT_LENGTH 1 #define NORMAL 0 #define STATE_SHORT 2 #define STATE_LONG 3 #define FORMAT_SPECIFIER 1 #define LENGTH_DEFAULT 0 #define LENGTH_SHORT_SHORT 1 #define LENGTH_SHORT 2 #define LENGTH_LONG 3 #define LENGTH_LONG_LONG 4 extern bool serial_enabled; void klog(const char *func, const char *msg, ...){ kprintf("{ksk}: {s}\n", ANSI_COLOR_MAGENTA, func, ANSI_COLOR_RESET, msg); serial_kprintf("{ksk}: {s}\n", ANSI_COLOR_MAGENTA, func, ANSI_COLOR_RESET, msg); return; } atomic_flag printf_lock = ATOMIC_FLAG_INIT; /* printf() params: string arguments available format specifiers: {i}, {d} - integer {s} - string {c} - char {k} - color {n} - newline (doesnt take in a argument) {x} - base16 {b} - binary */ int kprintf(const char *format_string, ...){ extern struct flanterm_context *ft_ctx; acquire_spinlock(&printf_lock); int state = NORMAL; va_list a_list; va_start(a_list, format_string); for(uint64_t i = 0; i < strlen(format_string); i++){ char current = format_string[i]; // current char in string switch (state){ case NORMAL: switch (current) { case '{': state = FORMAT_SPECIFIER; break; default: print_char(ft_ctx, current); break; } break; case FORMAT_SPECIFIER: switch (current) { case 'n': print_str(ft_ctx, "\n"); break; case 'k': print_str(ft_ctx, va_arg(a_list, char*)); break; case 'd': case 'i': print_int(ft_ctx, va_arg(a_list, long long)); break; case 's': print_str(ft_ctx, va_arg(a_list, char*)); break; case 'c': ; int ch = va_arg(a_list, int); print_char(ft_ctx, ch); break; case 'x': print_hex(ft_ctx, va_arg(a_list, uint64_t)); break; case 'b': print_bin(ft_ctx, va_arg(a_list, uint64_t)); break; case 'l': current++; switch (current) { case 'd': print_int(ft_ctx, va_arg(a_list, long long int)); break; } break; case '}': state = NORMAL; break; } break; } } va_end(a_list); free_spinlock(&printf_lock); return 0; } int serial_kprintf(const char *format_string, ...){ int state = NORMAL; va_list a_list; va_start(a_list, format_string); for(uint64_t i = 0; i < strlen(format_string); i++){ char current = format_string[i]; // current char in string switch (state){ case NORMAL: switch (current) { case '{': state = FORMAT_SPECIFIER; break; default: serial_print_char(current); break; } break; case FORMAT_SPECIFIER: switch (current) { case 'n': serial_print("\n"); break; case 'k': serial_print(va_arg(a_list, char*)); break; case 'd': case 'i': serial_print_int(va_arg(a_list, long long)); break; case 's': serial_print(va_arg(a_list, char*)); break; case 'c': ; int ch = va_arg(a_list, int); serial_print_char(ch); break; case 'x': serial_print_hex(va_arg(a_list, uint64_t)); break; case 'b': serial_print_bin(va_arg(a_list, uint64_t)); break; case 'l': current++; switch (current) { case 'd': case 'i': serial_print_int(va_arg(a_list, long long int)); break; } break; case '}': state = NORMAL; break; } break; } } va_end(a_list); return 0; } #define MAX_INTERGER_SIZE 128 void print_char(struct flanterm_context *ft_ctx, char c){ kernel_framebuffer_print(&c, 1); } void serial_print_char(char c){ serial_write(c); } void print_str(struct flanterm_context *ft_ctx, char *str){ kernel_framebuffer_print(str, strlen(str)); } void print_int(struct flanterm_context *ft_ctx, uint64_t num){ char buffer[MAX_INTERGER_SIZE] = {0}; if(num == 0){ buffer[0] = '0'; } int arr[MAX_INTERGER_SIZE] = {0}; int j = 0; while(num != 0){ int mod = num % 10; arr[j] = dtoc(mod); num /= 10; j++; if(j == MAX_INTERGER_SIZE){ return; } } /* Reverse buffer */ for(int i = 0; i < j; i++){ buffer[i] = arr[j - i - 1]; } kernel_framebuffer_print(buffer, strlen(buffer)); } void print_hex(struct flanterm_context *ft_ctx, uint64_t num){ char buffer[MAX_INTERGER_SIZE] = {0}; if(num == 0){ buffer[0] = '0'; } int arr[MAX_INTERGER_SIZE] = {0}; int j = 0; while(num != 0){ int mod = num % 16; arr[j] = dtoc(mod); num /= 16; j++; if(j == MAX_INTERGER_SIZE){ return; } } /* Reverse buffer */ for(int i = 0; i < j; i++){ buffer[i] = arr[j - i - 1]; } kernel_framebuffer_print(buffer, strlen(buffer)); } void print_bin(struct flanterm_context *ft_ctx, uint64_t num){ char buffer[MAX_INTERGER_SIZE] = {0}; int arr[MAX_INTERGER_SIZE] = {0}; int j = 0; while(num != 0){ int mod = num % 2; arr[j] = dtoc(mod); num /= 2; j++; if(j == MAX_INTERGER_SIZE){ return; } } /* Reverse buffer */ for(int i = 0; i < j; i++){ buffer[i] = arr[j - i - 1]; } kernel_framebuffer_print(buffer, strlen(buffer)); } void serial_print_int(uint64_t num){ char buffer[MAX_INTERGER_SIZE] = {0}; int arr[MAX_INTERGER_SIZE] = {0}; int j = 0; while(num != 0){ int mod = num % 10; arr[j] = dtoc(mod); num /= 10; j++; if(j == MAX_INTERGER_SIZE){ return; } } /* Reverse buffer */ for(int i = 0; i < j; i++){ buffer[i] = arr[j - i - 1]; } kernel_serial_print(buffer, strlen(buffer)); } void serial_print_hex(uint64_t num){ char buffer[MAX_INTERGER_SIZE] = {0}; int arr[MAX_INTERGER_SIZE] = {0}; int j = 0; while(num != 0){ int mod = num % 16; arr[j] = dtoc(mod); num /= 16; j++; if(j == MAX_INTERGER_SIZE){ return; } } /* Reverse buffer */ for(int i = 0; i < j; i++){ buffer[i] = arr[j - i - 1]; } kernel_serial_print(buffer, strlen(buffer)); } void serial_print_bin(uint64_t num){ char buffer[MAX_INTERGER_SIZE] = {0}; int arr[MAX_INTERGER_SIZE] = {0}; int j = 0; while(num != 0){ int mod = num % 2; arr[j] = dtoc(mod); num /= 2; j++; if(j == MAX_INTERGER_SIZE){ return; } } /* Reverse buffer */ for(int i = 0; i < j; i++){ buffer[i] = arr[j - i - 1]; } kernel_serial_print(buffer, strlen(buffer)); } char toupper(char c){ switch(c){ case 'a': return 'A'; case 'b': return 'B'; case 'c': return 'C'; case 'd': return 'D'; case 'e': return 'E'; case 'f': return 'F'; case 'g': return 'G'; case 'h': return 'H'; case 'i': return 'I'; case 'j': return 'J'; case 'k': return 'K'; case 'l': return 'L'; case 'm': return 'M'; case 'n': return 'N'; case 'o': return 'O'; case 'p': return 'P'; case 't': return 'T'; case 'r': return 'R'; case 's': return 'S'; case 'u': return 'U'; case 'v': return 'V'; case 'w': return 'W'; case 'x': return 'X'; case 'y': return 'Y'; case 'z': return 'Z'; default: return c; } } /* Eventually fix printf so that these print_* functions dont write to the framebuffer but instead return to printf */ /* Prints a char array to the framebuffer, thread safe*/ void kernel_framebuffer_print(char *buffer, size_t n){ extern struct flanterm_context *ft_ctx; flanterm_write(ft_ctx, buffer, n); } /* Prints a char array to serial, thread safe*/ void kernel_serial_print(char *buffer, size_t n){ for(size_t i = 0; i < n; i++){ serial_print_char(buffer[i]); } }