Debug helpers
This commit is contained in:
parent
eea52c1717
commit
5276d5e882
124
src/kernel/boot/debug.c
Normal file
124
src/kernel/boot/debug.c
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
#include <stddef.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <vga.h>
|
||||||
|
|
||||||
|
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<i)
|
||||||
|
{
|
||||||
|
char t = buf[i];
|
||||||
|
buf[i--] = buf[j];
|
||||||
|
buf[j++] = t;
|
||||||
|
}
|
||||||
|
buf[i+j+1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
void debug_putch(char c)
|
||||||
|
{
|
||||||
|
vga_write(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void debug_putsn(char *s, size_t n)
|
||||||
|
{
|
||||||
|
while(n--)
|
||||||
|
debug_putch(*s++);
|
||||||
|
}
|
||||||
|
|
||||||
|
void debug_puts(char *s)
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
while(s[len]) len++;
|
||||||
|
debug_putsn(s, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void debug_vprintf(char *fmt, va_list args)
|
||||||
|
{
|
||||||
|
if(!(*fmt))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(*fmt != '%')
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
while(fmt[len] && fmt[len] != '%')
|
||||||
|
len++;
|
||||||
|
debug_putsn(fmt, len);
|
||||||
|
debug_vprintf(&fmt[len], args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt++;
|
||||||
|
size_t padwidth = 0;
|
||||||
|
char padchar = ' ';
|
||||||
|
if(*fmt == '0')
|
||||||
|
{
|
||||||
|
padchar = '0';
|
||||||
|
fmt++;
|
||||||
|
}
|
||||||
|
while(*fmt >= '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);
|
||||||
|
}
|
@ -1,4 +1,6 @@
|
|||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
|
#include <vga.h>
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
void clear_screen()
|
void clear_screen()
|
||||||
{
|
{
|
||||||
@ -19,7 +21,13 @@ void print_string(char *str)
|
|||||||
|
|
||||||
void kmain()
|
void kmain()
|
||||||
{
|
{
|
||||||
clear_screen();
|
vga_init();
|
||||||
print_string("Hello from c, world!");
|
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(;;);
|
for(;;);
|
||||||
}
|
}
|
73
src/kernel/drivers/vga.c
Normal file
73
src/kernel/drivers/vga.c
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
#include <vga.h>
|
||||||
|
#include <memory.h>
|
||||||
|
#include <ports.h>
|
||||||
|
|
||||||
|
#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();
|
||||||
|
}
|
40
src/kernel/include/debug.h
Normal file
40
src/kernel/include/debug.h
Normal file
@ -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)
|
||||||
|
|
@ -11,9 +11,20 @@
|
|||||||
#define P2V(a) ((void *)((uintptr_t)(a) | KERNEL_OFFSET))
|
#define P2V(a) ((void *)((uintptr_t)(a) | KERNEL_OFFSET))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PAGE_SIZE 0x1000
|
|
||||||
|
|
||||||
#define PAGE_PRESENT 0x001
|
#define PAGE_PRESENT 0x001
|
||||||
#define PAGE_WRITE 0x002
|
#define PAGE_WRITE 0x002
|
||||||
|
|
||||||
#define ENTRIES_PER_PT 512
|
#define PAGE_SIZE 0x1000
|
||||||
|
#define ENTRIES_PER_PT 512
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLER__
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
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
|
17
src/kernel/include/ports.h
Normal file
17
src/kernel/include/ports.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
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
|
7
src/kernel/include/vga.h
Normal file
7
src/kernel/include/vga.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <memory.h>
|
||||||
|
|
||||||
|
#define VGA_MEMORY P2V(0xB8000)
|
||||||
|
|
||||||
|
void vga_init();
|
||||||
|
void vga_write(char c);
|
55
src/kernel/memory/string.c
Normal file
55
src/kernel/memory/string.c
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#include <memory.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user