aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/kprintf.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/kprintf.c')
-rw-r--r--kernel/kprintf.c259
1 files changed, 259 insertions, 0 deletions
diff --git a/kernel/kprintf.c b/kernel/kprintf.c
new file mode 100644
index 0000000..20769ea
--- /dev/null
+++ b/kernel/kprintf.c
@@ -0,0 +1,259 @@
+#include <stdbool.h>
+
+#include "kprintf.h"
+
+#include "asm_inline.h"
+
+// #define KDEBUG
+
+int check_transmission() {
+ return inb(COM1 + 5) & 0x20;
+}
+
+void write_serial_char(char a) {
+ while (check_transmission() == 0);
+ outb(COM1,a);
+}
+
+void write_serial_string(const char* str)
+{
+ while(*str != '\0')
+ {
+ if(*str == '\n')
+ {
+ write_serial_char('\r');
+ }
+ write_serial_char(*str);
+ str++;
+ }
+}
+
+char* convert_U_integer(uint64_t n, uint16_t base, bool caps)
+{
+ static char* format = "0123456789abcdef";
+ static char* C_format = "0123456789ABCDEF";
+
+ static char buffer[50];
+ char *ptr;
+
+ ptr = &buffer[49];
+ *ptr = '\0';
+
+ do
+ {
+ if(caps)
+ {
+ *--ptr = C_format[n%base];
+ }
+ else
+ {
+ *--ptr = format[n%base];
+ }
+ n /= base;
+ } while(n != 0);
+
+ return ptr;
+}
+
+void kprintf(const char* str, ...)
+{
+ va_list args;
+
+ va_start(args, str);
+
+ while(*str)
+ {
+ if(*str == '%')
+ {
+ #ifdef KDEBUG
+ write_serial_string("{stradv}");
+ #endif
+ str++;
+ if(*str == 'i' || *str == 'd')
+ {
+ #ifdef KDEBUG
+ write_serial_string("[INT]");
+ #endif
+ int32_t n = va_arg(args, int32_t);
+ char* s = convert_U_integer(n, 10, false);
+ write_serial_string(s);
+ }
+ else if(*str == 'u')
+ {
+ #ifdef KDEBUG
+ write_serial_string("[UINT]");
+ #endif
+ uint32_t n = va_arg(args, uint32_t);
+ char* s = convert_U_integer(n, 10, false);
+ write_serial_string(s);
+ }
+ else if(*str == 'x')
+ {
+ #ifdef KDEBUG
+ write_serial_string("[HEX]");
+ #endif
+ uint32_t n = va_arg(args, uint32_t);
+ char* s = convert_U_integer(n, 16, false);
+ write_serial_string("0x");
+ write_serial_string(s);
+ }
+ else if(*str == 'X')
+ {
+ #ifdef KDEBUG
+ write_serial_string("[HEX]");
+ #endif
+ uint32_t n = va_arg(args, uint32_t);
+ char* s = convert_U_integer(n, 16, true);
+ write_serial_string("0x");
+ write_serial_string(s);
+ }
+ else if(*str == 'l')
+ {
+ #ifdef KDEBUG
+ write_serial_string("[LONG]");
+ write_serial_string("{ladv}");
+ #endif
+ str++;
+ if(*str == 'i' || *str == 'd')
+ {
+ #ifdef KDEBUG
+ write_serial_string("[INT]");
+ #endif
+ int64_t n = va_arg(args, int64_t);
+ char* s = convert_U_integer(n, 10, false);
+ write_serial_string(s);
+ }
+ else if(*str == 'u')
+ {
+ #ifdef KDEBUG
+ write_serial_string("[UINT]");
+ #endif
+ uint64_t n = va_arg(args, uint64_t);
+ char* s = convert_U_integer(n, 10, false);
+ write_serial_string(s);
+ }
+ else if(*str == 'x')
+ {
+ #ifdef KDEBUG
+ write_serial_string("[HEX]");
+ #endif
+ uint64_t n = va_arg(args, uint64_t);
+ char* s = convert_U_integer(n, 16, false);
+ write_serial_string("0x");
+ write_serial_string(s);
+ }
+ else if(*str == 'X')
+ {
+ #ifdef KDEBUG
+ write_serial_string("[HEX]");
+ #endif
+ uint64_t n = va_arg(args, uint64_t);
+ char* s = convert_U_integer(n, 16, true);
+ write_serial_string("0x");
+ write_serial_string(s);
+ }
+ }
+ else if(*str == 'h')
+ {
+ #ifdef KDEBUG
+ write_serial_string("[SHORT]");
+ write_serial_string("{ladv}");
+ #endif
+ str++;
+ if(*str == 'i' || *str == 'd')
+ {
+ #ifdef KDEBUG
+ write_serial_string("[INT]");
+ #endif
+ int16_t n = va_arg(args, int);
+ char* s = convert_U_integer(n, 10, false);
+ write_serial_string(s);
+ }
+ else if(*str == 'u')
+ {
+ #ifdef KDEBUG
+ write_serial_string("[UINT]");
+ #endif
+ uint16_t n = va_arg(args, int);
+ char* s = convert_U_integer(n, 10, false);
+ write_serial_string(s);
+ }
+ else if(*str == 'x')
+ {
+ #ifdef KDEBUG
+ write_serial_string("[HEX]");
+ #endif
+ uint16_t n = va_arg(args, int);
+ char* s = convert_U_integer(n, 16, false);
+ write_serial_string("0x");
+ write_serial_string(s);
+ }
+ else if(*str == 'X')
+ {
+ #ifdef KDEBUG
+ write_serial_string("[HEX]");
+ #endif
+ uint16_t n = va_arg(args, int);
+ char* s = convert_U_integer(n, 16, true);
+ write_serial_string("0x");
+ write_serial_string(s);
+ }
+ }
+ else if(*str == 'p')
+ {
+ #ifdef KDEBUG
+ write_serial_string("[PTR]");
+ #endif
+ void* p = va_arg(args, void*);
+ uint64_t n = (uint64_t)p;
+ char* s = convert_U_integer(n, 16, true);
+ write_serial_string("0x");
+ write_serial_string(s);
+ }
+ else if(*str == 'c')
+ {
+ #ifdef KDEBUG
+ write_serial_string("[CHAR]");
+ #endif
+ char c = va_arg(args, int);
+ write_serial_char(c);
+ }
+ else if(*str == 's')
+ {
+ #ifdef KDEBUG
+ write_serial_string("[STR]");
+ #endif
+ char* s = va_arg(args, char*);
+ write_serial_string(s);
+ }
+ else
+ {
+ write_serial_string("\nFailed to write malformed kprintf: ");
+ write_serial_char(*str);
+ write_serial_string("\n");
+ va_end(args);
+ return;
+ }
+ #ifdef KDEBUG
+ write_serial_string("{pend}");
+ #endif
+ }
+ else if(*str == '\n')
+ {
+ write_serial_char('\r');
+ write_serial_char('\n');
+ }
+ else
+ {
+ write_serial_char(*str);
+ }
+ #ifdef KDEBUG
+ write_serial_string("{oadv}");
+ #endif
+ str++;
+ }
+
+ //write_serial_string(str);
+
+ va_end(args);
+}