diff --git a/kernel/include/kernel.h b/kernel/include/kernel.h index 626b636..5973ea0 100644 --- a/kernel/include/kernel.h +++ b/kernel/include/kernel.h @@ -2,15 +2,16 @@ #define _KERNEL_H // Null definition -#define NULL ((void*)0) +#define NULL ((void*)0) /* * Variable arguments */ typedef void* va_list; -#define va_start(ap, param) (void)((ap) = (char*)(&(param) + 1)) -#define va_end(ap) (void)((ap) = 0) -#define va_arg(ap, type) (((type*)((ap) = ((ap) + sizeof(type))))[-1]) +#define __va_align(size) ((size + sizeof(int) - 1) & ~(sizeof(int) - 1)) +#define va_start(ap, param) (void)((ap) = (char*)(&(param) + 1)) +#define va_end(ap) (void)((ap) = 0) +#define va_arg(ap, type) (*(type*)(((ap) += __va_align(sizeof(type))) - sizeof(type))) /* * Utility macros @@ -67,6 +68,11 @@ typedef int32_t intptr_t; #define true 1 #define false 0 +/* + * Linker defined values + */ +extern uint32_t __kernel_start, __kernel_end; + /* * Logging and errors */ diff --git a/kernel/include/vsnprintf.h b/kernel/include/vsnprintf.h new file mode 100644 index 0000000..dd9771f --- /dev/null +++ b/kernel/include/vsnprintf.h @@ -0,0 +1,8 @@ +#ifndef _VSNPRINTF_H +#define _VSNPRINTF_H + +#include + +int vsnprintf(char* buf, size_t len, char* fmt, va_list args); + +#endif diff --git a/kernel/src/entry.s b/kernel/src/entry.s index 0200a2a..3f87166 100644 --- a/kernel/src/entry.s +++ b/kernel/src/entry.s @@ -31,6 +31,7 @@ global _start extern kmain _start: mov esp, stack_top ; Setup stack + push eax push ebx call kmain ; Call kernel main diff --git a/kernel/src/kernel.c b/kernel/src/kernel.c index ac4f070..50fc878 100644 --- a/kernel/src/kernel.c +++ b/kernel/src/kernel.c @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -6,43 +6,30 @@ #define _hlt() while (1) __asm__ volatile ("cli; hlt"); -char* itoa(uint8_t n) { - static char str[32]; - int i = sizeof(str) - 2; - while (n) { - str[i--] = (n % 10) + '0'; - n /= 10; - } - str[sizeof(str) - 1] = '\0'; - return &str[i+1]; -} - __noreturn -void kmain(void* ptr) { - multiboot_info_t* mbi = ptr; +void kmain(void* ptr, uint32_t magic) { + // Init with MultiBoot 1, this populates the global bootloader struct + //if (boot_init(BOOT_MB1, ptr, magic) != 0) panic("Unsupporred bootloader."); // Serial console for debugging serial_init(COM1); serial_puts(COM1, "\x1b[0H\x1b[Jkern.\n"); - // Check if we have a valid memmap - if (!(mbi->flags >> 6 & 1)) { - panic("Invalid memory map."); - } - // VGA tty thingy tty_init(); - tty_puts("kern."); + tty_puts("kern.\n\n"); // Memory manager init // pmm_init(); // vmm_init(); - // x86 shit // gdt_init(); // isr_init(); + // pag_init(); + + debugf("Basic initialization complete!\n"); - /* TODO: Commeted out stuff */ + /* TODO: Commented out stuff */ panic("kmain() reached end."); } diff --git a/kernel/src/serial.c b/kernel/src/serial.c index 69633a0..a199d79 100644 --- a/kernel/src/serial.c +++ b/kernel/src/serial.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -51,3 +52,18 @@ void serial_puts(int dev, char* s) { serial_write(dev, s, len); } +int debugf(char* fmt, ...) { + va_list args; + va_start(args, fmt); + int ret = vdebugf(fmt, args); + va_end(args); + return ret; +} + +int vdebugf(char* fmt, va_list args) { + static char buf[DF_BUF_LEN]; + int ret = vsnprintf(buf, DF_BUF_LEN, fmt, args); + serial_puts(COM1, buf); + return ret; +} + diff --git a/kernel/src/tty.c b/kernel/src/tty.c index d38e22a..6932db7 100644 --- a/kernel/src/tty.c +++ b/kernel/src/tty.c @@ -89,7 +89,7 @@ scroll_check: void tty_write(char* buf, size_t len) { ctx.updateWait = len - 1; - for (int i = 0; i < len; i++) tty_putc(buf[i]); + for (size_t i = 0; i < len; i++) tty_putc(buf[i]); } void tty_puts(char* s) { diff --git a/kernel/src/vsnprintf.c b/kernel/src/vsnprintf.c new file mode 100644 index 0000000..544ecc7 --- /dev/null +++ b/kernel/src/vsnprintf.c @@ -0,0 +1,93 @@ +#include +#include + +int pf_isdigit(char c) { + if (c >= '0' && c <= '9') return 1; + return 0; +} + +char* pf_itoa(uint32_t num, uint8_t base) { + static char buf[32]; + + if (base == 0 || base > 16) return NULL; + + if (num == 0) { + buf[0] = '0'; + buf[1] = '\0'; + return &buf[0]; + } + + int i; + for (i = 30; num && i; i--, num /= base) { + buf[i] = "0123456789abcdef"[num % base]; + } + + return &buf[i + 1]; +} + +char* pf_ftoa(float f) { + return NULL; +} + +int vsnprintf(char* buf, size_t len, char* fmt, va_list args) { + size_t i = 0; + + while (*fmt != '\0' && i < len) { + if (*fmt != '%') { + if (i < len) buf[i++] = *fmt++; + continue; + } + + fmt++; // Consume the '%' + if (*fmt == '\0') { + if (i < len) buf[i++] = '%'; + break; + } + + // Parse the format specifier + int width = 0; + char pad = ' '; + + if (pf_isdigit(*fmt)) { + if (*fmt == '0') { pad = '0'; fmt++; } + + while (pf_isdigit(*fmt)) { + width *= 10; + width += *fmt++ - '0'; + } + } + + char* s; + switch (*fmt) { + case 'c': // Char + if (i < len) buf[i++] = (char)va_arg(args, int); + break; + case 'd': // Int (TODO: %d for signed, %u for unsigned + s = pf_itoa(va_arg(args, unsigned int), 10); + goto string; + case 'x': // Unsigned hex int + s = pf_itoa(va_arg(args, unsigned int), 16); + goto string; + case 'f': // Float + s = pf_ftoa(va_arg(args, double)); + goto string; + case 's': // String + s = va_arg(args, char*); + string: // Prints the string in s + if (s == NULL) s = "(null)"; + while (*s != '\0' && i < len) buf[i++] = *s++; + break; + default: // Something else + if (i < len) buf[i++] = '%'; + if (i < len) buf[i++] = *fmt; + break; + } + + fmt++; + } + + if (i < len) buf[i++] = '\0'; + + return i; +} +