diff --git a/src/kernel/boot/debug.c b/src/kernel/boot/debug.c new file mode 100644 index 0000000..4a74efd --- /dev/null +++ b/src/kernel/boot/debug.c @@ -0,0 +1,124 @@ +#include +#include +#include +#include + +void num2str(char *buf, uint64_t num, uint64_t base) +{ + if(num == 0) + { + buf[0] = '0'; + buf[1] = '\0'; + return; + } + uint64_t i=0, j=0; + char chars[] = "0123456789ABCDEF"; + while(num > 0) + { + buf[i++] = chars[num%base]; + num /= base; + } + i--; + while(j= '0' && *fmt <='9') + { + padwidth *= 10; + padwidth += (int)(*fmt++ - '0'); + } + uint64_t base = 0; + switch(*fmt) + { + case 'b': + base = 2; + break; + case 'o': + base = 8; + break; + case 'd': + base = 10; + break; + case 'x': + base = 16; + break; + case 'c': + debug_putch((char)va_arg(args, uint64_t)); + break; + case 's': + debug_puts(va_arg(args, char*)); + break; + default: + debug_putch('%'); + fmt--; + } + + if(base) + { + uintmax_t number = va_arg(args, uintmax_t); + char buf[128]; + num2str(buf, number, base); + if(padwidth > strlen(buf)) + for(size_t i = 0; i < (padwidth - strlen(buf)); i++) + debug_putch(padchar); + debug_puts(buf); + } + + fmt++; + debug_vprintf(fmt, args); +} + +void debug_printf(char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + debug_vprintf(fmt, args); + va_end(args); +} \ No newline at end of file diff --git a/src/kernel/boot/kmain.c b/src/kernel/boot/kmain.c index 3506fda..e7277e8 100644 --- a/src/kernel/boot/kmain.c +++ b/src/kernel/boot/kmain.c @@ -1,4 +1,6 @@ #include +#include +#include void clear_screen() { @@ -19,7 +21,13 @@ void print_string(char *str) void kmain() { - clear_screen(); - print_string("Hello from c, world!"); + vga_init(); + debug("Hello, world!"); + int value = 123; + debug_info("dec: %d hex: %x, binary: %b", value, value, value); + + PANIC("End of kernel function!"); + + debug_info("Broke out of panic") for(;;); } \ No newline at end of file diff --git a/src/kernel/drivers/vga.c b/src/kernel/drivers/vga.c new file mode 100644 index 0000000..dd4ac38 --- /dev/null +++ b/src/kernel/drivers/vga.c @@ -0,0 +1,73 @@ +#include +#include +#include + +#define VGA_COLS 80 +#define VGA_ROWS 24 +#define VGA_SIZE (VGA_COLS*VGA_ROWS) + +#define VGA_ROW(pos) ((pos)/VGA_COLS) +#define VGA_COL(pos) ((pos)%VGA_COLS) +#define VGA_POS(row, col) ((row)*VGA_COLS + (col)) + +#define VGA_ADDRESS_PORT 0x3D4 +#define VGA_DATA_PORT 0x3D5 +#define VGA_REGISTER_CURSOR_POS_LOW 0xF +#define VGA_REGISTER_CURSOR_POS_HIGH 0xE + +void *vidmem; +struct vga_cell{ + uint8_t c; + uint8_t f; +}__attribute__((packed)); + +struct vga_cell buffer[VGA_SIZE]; + +uint64_t cursor; +uint8_t format; + +void vga_init() +{ + vidmem = VGA_MEMORY; + memset(vidmem, 0, VGA_SIZE*sizeof(struct vga_cell)); + + format = 0x07; +} + +void movecursor() +{ + outb(VGA_ADDRESS_PORT, VGA_REGISTER_CURSOR_POS_LOW); + outb(VGA_DATA_PORT, (uint8_t)(cursor & 0xFF)); + outb(VGA_ADDRESS_PORT, VGA_REGISTER_CURSOR_POS_HIGH); + outb(VGA_DATA_PORT, (uint8_t)((cursor >> 8) & 0xFF)); +} + +void flush() +{ + memcpy(vidmem, buffer, sizeof(buffer)); +} + +void scroll() +{ + while(cursor >= VGA_SIZE) + { + memmove(buffer, &buffer[VGA_POS(1,0)], VGA_COLS*(VGA_ROWS-1)*sizeof(struct vga_cell)); + memset(&buffer[VGA_POS(VGA_ROWS-1, 0)], 0, VGA_COLS*sizeof(struct vga_cell)); + cursor -= VGA_COLS; + } +} + +void vga_write(char c) +{ + switch(c) + { + case '\n': + cursor += VGA_COLS - VGA_COL(cursor); + break; + default: + buffer[cursor++] = (struct vga_cell){.c = c, .f = format}; + } + scroll(); + flush(); + movecursor(); +} \ No newline at end of file diff --git a/src/kernel/include/debug.h b/src/kernel/include/debug.h new file mode 100644 index 0000000..3083eae --- /dev/null +++ b/src/kernel/include/debug.h @@ -0,0 +1,40 @@ +#pragma once + +#ifndef NDEBUG +#define debug(...) debug_printf(__VA_ARGS__) +#define debug_info(...) \ + do{debug("[INFO] "); debug(__VA_ARGS__);}while(0) +#define debug_ok(...) \ + do{debug("[OK] "); debug(__VA_ARGS__);}while(0) +#define debug_warning(...) \ + do{debug("[WARNING] "); debug(__VA_ARGS__);}while(0) +#define debug_error(...) \ + do{debug("[ERROR] "); debug(__VA_ARGS__);}while(0) +#else +#define debug(...) +#define debug_info(...) +#define debug_ok(...) +#define debug_warning(...) +#define debug_error(...) +#endif + +void debug_printf(char *fmt, ...); +void debug_puts(char *s); +void debug_putsn(char *s, size_t n); +void debug_putsh(char c); + +#define S(x) #x +#define S_(x) S(x) +#define S__LINE__ S_(__LINE__) + +#define PANIC(...) \ + do { \ + debug_printf("\n\nKERNEL PANIC!\n%s:%d\n", __FILE__, __LINE__); \ + debug_printf(__VA_ARGS__); \ + volatile int _override = 0; \ + while(1) { \ + asm("panic_breakpoint_" S__LINE__ ":"); \ + if(_override) break; \ + } \ + }while(0) + \ No newline at end of file diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index 94a500e..5de76a9 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -11,9 +11,20 @@ #define P2V(a) ((void *)((uintptr_t)(a) | KERNEL_OFFSET)) #endif -#define PAGE_SIZE 0x1000 #define PAGE_PRESENT 0x001 #define PAGE_WRITE 0x002 -#define ENTRIES_PER_PT 512 \ No newline at end of file +#define PAGE_SIZE 0x1000 +#define ENTRIES_PER_PT 512 + +#ifndef __ASSEMBLER__ +#include + +void *memcpy(void *dst, const void *src, size_t n); +void *memset(void *s, int c, size_t n); +void *memmove(void *dest, const void *src, size_t n); +int memcmp(const void *s1, const void *s2, size_t n); +size_t strlen(const char *s); + +#endif \ No newline at end of file diff --git a/src/kernel/include/ports.h b/src/kernel/include/ports.h new file mode 100644 index 0000000..b176149 --- /dev/null +++ b/src/kernel/include/ports.h @@ -0,0 +1,17 @@ +#pragma once +#include + +static __inline void _outb(uint16_t port, uint8_t value) +{ + asm volatile("outb %1, %0" : : "dN" (port), "a" (value)); +} + +static __inline uint8_t _inb(uint16_t port) +{ + uint8_t ret; + asm volatile("inb %1, %0" : "=a" (ret) : "dN" (port)); + return ret; +} + +#define outb _outb +#define inb _inb \ No newline at end of file diff --git a/src/kernel/include/vga.h b/src/kernel/include/vga.h new file mode 100644 index 0000000..03fda32 --- /dev/null +++ b/src/kernel/include/vga.h @@ -0,0 +1,7 @@ +#pragma once +#include + +#define VGA_MEMORY P2V(0xB8000) + +void vga_init(); +void vga_write(char c); \ No newline at end of file diff --git a/src/kernel/memory/string.c b/src/kernel/memory/string.c new file mode 100644 index 0000000..d27a142 --- /dev/null +++ b/src/kernel/memory/string.c @@ -0,0 +1,55 @@ +#include +#include +#include + +void *memcpy(void *dst, const void *src, size_t n) +{ + char *dp = dst; + const char *sp = src; + while(n--) *dp++ = *sp++; + return dst; +} + +void *memset(void *s, int c, size_t n) +{ + unsigned char *p = s; + while(n--) *p++ = (unsigned char)c; + return s; +} + +void *memmove(void *dst, const void *src, size_t n) +{ + if(src == dst) + return dst; + + const void *src_end = (const void *)((uintptr_t)src + n); + if(src < dst && dst < src_end) + { + char *dp = dst; + const char *sp = src; + while(n--) + dp[n] = sp[n]; + return dst; + } + + memcpy(dst, src, n); + return dst; +} + +int memcmp(const void *s1, const void *s2, size_t n) +{ + const unsigned char *p1 = s1, *p2 = s2; + for(; n--; p1++, p2++) + { + if(*p1 != *p2) + return *p1 - *p2; + } + return 0; +} + +size_t strlen(const char *s) +{ + size_t len = 0; + while(*s++) len++; + return len; +} \ No newline at end of file