This commit is contained in:
nub31
2025-09-01 20:06:58 +02:00
parent 1bc122e29a
commit 1ed52d1e9e
14 changed files with 154 additions and 223 deletions

View File

@@ -63,27 +63,17 @@ static const char* exception_messages[32] = {
void handle_exception(const isr_frame_t* frame) void handle_exception(const isr_frame_t* frame)
{ {
vga_print_error(); kprintf("exception[%d]: %s, error code: %d\n", frame->int_no, exception_messages[frame->int_no], frame->err_code);
vga_print(" exception["); kpanic();
vga_print_uint(frame->int_no);
vga_print("]: ");
vga_print(exception_messages[frame->int_no]);
vga_print(", error code: ");
vga_print_uint(frame->err_code);
vga_print("\n");
kernel_panic();
} }
static irq_handler_t irq_handlers[16] = {0}; static irq_handler_t irq_handlers[16] = {0};
void register_irq_handler(u8 irq, irq_handler_t handler) void register_irq_handler(uint8_t irq, irq_handler_t handler)
{ {
if (irq >= 16) if (irq >= 16)
{ {
vga_print_error(); kprintf("Cannot register irq %d is out of bounds\n", irq);
vga_print("Cannot register irq ");
vga_print_uint(irq);
vga_print(" is out of bounds\n");
} }
else else
{ {
@@ -93,7 +83,7 @@ void register_irq_handler(u8 irq, irq_handler_t handler)
void handle_irq(const isr_frame_t* frame) void handle_irq(const isr_frame_t* frame)
{ {
u8 irq = frame->int_no - 32; uint8_t irq = frame->int_no - 32;
if (irq_handlers[irq]) if (irq_handlers[irq])
{ {
@@ -110,7 +100,7 @@ void handle_irq(const isr_frame_t* frame)
void handle_isr(const isr_frame_t* frame) void handle_isr(const isr_frame_t* frame)
{ {
vga_print("test"); kprintf("isr");
if (frame->int_no < 32) if (frame->int_no < 32)
{ {
@@ -122,10 +112,6 @@ void handle_isr(const isr_frame_t* frame)
} }
else else
{ {
vga_print_error(); kprintf("interrupt[%d]: not implemented\n", frame->int_no);
vga_print(" interrupt[");
vga_print_uint(frame->int_no);
vga_print("]: ");
vga_print("not implemented\n");
} }
} }

View File

@@ -1,21 +1,21 @@
#pragma once #pragma once
#include "typedef.h" #include <stdint.h>
typedef struct typedef struct
{ {
u64 r15, r14, r13, r12, r11, r10, r9, r8; uint64_t r15, r14, r13, r12, r11, r10, r9, r8;
u64 rbp, rdi, rsi, rdx, rcx, rbx, rax; uint64_t rbp, rdi, rsi, rdx, rcx, rbx, rax;
u64 int_no; uint64_t int_no;
u64 err_code; uint64_t err_code;
u64 rip, cs, rflags, rsp, ss; uint64_t rip, cs, rflags, rsp, ss;
} __attribute__((packed)) isr_frame_t; } __attribute__((packed)) isr_frame_t;
typedef void (*irq_handler_t)(const isr_frame_t*); typedef void (*irq_handler_t)(const isr_frame_t*);
void pic_remap(); void pic_remap();
void register_irq_handler(u8 irq, irq_handler_t handler); void register_irq_handler(uint8_t irq, irq_handler_t handler);
static inline void enable_interrupts() static inline void enable_interrupts()
{ {

View File

@@ -1,21 +1,67 @@
#include "kernel.h" #include "kernel.h"
#include "interrupts.h" #include "interrupts.h"
#include "string.h"
#include "vga.h" #include "vga.h"
#include <stdarg.h>
#include <stddef.h>
void kernel_main() void kmain()
{ {
vga_clear(); vga_clear();
pic_remap(); pic_remap();
enable_interrupts(); enable_interrupts();
vga_print("\nWelcome to nub OS\n"); kprintf("\nWelcome to nub OS\n");
kernel_halt(); khalt();
} }
void kernel_panic() void kpanic()
{ {
vga_print("Kernel panic!\n"); kprintf("Kernel panic!\n");
kernel_halt(); khalt();
}
void kprintf(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
for (size_t i = 0; fmt[i] != '\0'; i++)
{
if (fmt[i] == '%')
{
i++;
if (fmt[i] == 's')
{
const char* str = va_arg(args, const char*);
for (size_t j = 0; str[j] != '\0'; j++)
{
vga_put_char(str[j], 0x0F);
}
}
else if (fmt[i] == 'd')
{
int val = va_arg(args, int);
char buf[12];
itoa(val, buf);
for (size_t j = 0; buf[j] != '\0'; j++)
{
vga_put_char(buf[j], 0x0F);
}
}
else
{
vga_put_char('%', 0x0F);
vga_put_char(fmt[i], 0x0F);
}
}
else
{
vga_put_char(fmt[i], 0x0F);
}
}
va_end(args);
} }

View File

@@ -1,12 +1,14 @@
#pragma once #pragma once
void kernel_panic(); void kpanic();
static inline void kernel_halt() static inline void khalt()
{ {
while (true) while (true)
{ {
__asm__ volatile ("cli"); __asm__ volatile ("cli");
__asm__ volatile ("hlt"); __asm__ volatile ("hlt");
} }
} }
void kprintf(const char* fmt, ...);

View File

@@ -33,7 +33,7 @@ bool caps_lock = false;
static keyboard_handler_t keyboard_handlers[KEYBOARD_HANDLERS_LENGTH]; static keyboard_handler_t keyboard_handlers[KEYBOARD_HANDLERS_LENGTH];
static int handler_index = 0; static int handler_index = 0;
char scan_code_to_ascii(u8 scan_code) char scan_code_to_ascii(uint8_t scan_code)
{ {
if (scan_code >= 128) if (scan_code >= 128)
{ {
@@ -52,8 +52,8 @@ char scan_code_to_ascii(u8 scan_code)
void handle_keyboard(const isr_frame_t* frame) void handle_keyboard(const isr_frame_t* frame)
{ {
u8 code = inb(0x60); uint8_t code = inb(0x60);
u8 scan_code = code & 0x7F; uint8_t scan_code = code & 0x7F;
bool pressed = (code & 0x80) == 0; bool pressed = (code & 0x80) == 0;
switch (scan_code) switch (scan_code)
@@ -82,7 +82,7 @@ void handle_keyboard(const isr_frame_t* frame)
.ascii = scan_code_to_ascii(scan_code), .ascii = scan_code_to_ascii(scan_code),
}; };
for (int i = 0; i < handler_index; i++) for (size_t i = 0; i < handler_index; i++)
{ {
keyboard_handlers[i](&event); keyboard_handlers[i](&event);
} }
@@ -96,9 +96,8 @@ void register_keypress_handler(const keyboard_handler_t handler)
// keyboard_handlers is a dynamic list // keyboard_handlers is a dynamic list
if (handler_index >= KEYBOARD_HANDLERS_LENGTH) if (handler_index >= KEYBOARD_HANDLERS_LENGTH)
{ {
vga_print_error(); kprintf("Maximum keyboard handlers reached\n");
vga_print(" Maximum keyboard handlers reached\n"); kpanic();
kernel_panic();
} }
keyboard_handlers[handler_index] = handler; keyboard_handlers[handler_index] = handler;

View File

@@ -1,10 +1,10 @@
#pragma once #pragma once
#include "typedef.h" #include <stdint.h>
typedef struct typedef struct
{ {
u8 scan_code; uint8_t scan_code;
bool pressed; bool pressed;
bool shift; bool shift;
bool caps_lock; bool caps_lock;
@@ -15,4 +15,4 @@ typedef void (*keyboard_handler_t)(const keyboard_event_t*);
void init_keyboard(); void init_keyboard();
void register_keypress_handler(keyboard_handler_t handler); void register_keypress_handler(keyboard_handler_t handler);
char scan_code_to_ascii(u8 scan_code); char scan_code_to_ascii(uint8_t scan_code);

View File

@@ -1,59 +1,59 @@
#pragma once #pragma once
#include "typedef.h" #include <stdint.h>
typedef struct multiboot_info typedef struct multiboot_info
{ {
u32 flags; // required uint32_t flags; // required
// Available if flags[0] is set // Available if flags[0] is set
u32 mem_lower; uint32_t mem_lower;
u32 mem_upper; uint32_t mem_upper;
// Available if flags[1] is set // Available if flags[1] is set
u32 boot_device; uint32_t boot_device;
// Available if flags[2] is set // Available if flags[2] is set
u32 cmdline; uint32_t cmdline;
// Available if flags[3] is set // Available if flags[3] is set
u32 mods_count; uint32_t mods_count;
u32 mods_addr; uint32_t mods_addr;
// Available if flags[4] or flags[5] is set // Available if flags[4] or flags[5] is set
u8 syms[16]; // 28 - 40 bytes, exact layout may differ depending on a.out or ELF uint8_t syms[16]; // 28 - 40 bytes, exact layout may differ depending on a.out or ELF
// Available if flags[6] is set // Available if flags[6] is set
u32 mmap_length; uint32_t mmap_length;
u32 mmap_addr; uint32_t mmap_addr;
// Available if flags[7] is set // Available if flags[7] is set
u32 drives_length; uint32_t drives_length;
u32 drives_addr; uint32_t drives_addr;
// Available if flags[8] is set // Available if flags[8] is set
u32 config_table; uint32_t config_table;
// Available if flags[9] is set // Available if flags[9] is set
u32 boot_loader_name; uint32_t boot_loader_name;
// Available if flags[10] is set // Available if flags[10] is set
u32 apm_table; uint32_t apm_table;
// Available if flags[11] is set // Available if flags[11] is set
u32 vbe_control_info; uint32_t vbe_control_info;
u32 vbe_mode_info; uint32_t vbe_mode_info;
u16 vbe_mode; uint16_t vbe_mode;
u16 vbe_interface_seg; uint16_t vbe_interface_seg;
u16 vbe_interface_off; uint16_t vbe_interface_off;
u16 vbe_interface_len; uint16_t vbe_interface_len;
// Available if flags[12] is set // Available if flags[12] is set
u64 framebuffer_addr; // 64-bit for large memory addresses uint64_t framebuffer_addr; // 64-bit for large memory addresses
u32 framebuffer_pitch; uint32_t framebuffer_pitch;
u32 framebuffer_width; uint32_t framebuffer_width;
u32 framebuffer_height; uint32_t framebuffer_height;
u8 framebuffer_bpp; uint8_t framebuffer_bpp;
u8 framebuffer_type; uint8_t framebuffer_type;
u8 color_info[6]; // 110-115 bytes uint8_t color_info[6]; // 110-115 bytes
} __attribute__((packed)) multiboot_info_t; } __attribute__((packed)) multiboot_info_t;

View File

@@ -1,5 +1,5 @@
global _start global _start
extern kernel_main extern kmain
extern handle_isr extern handle_isr
%define FLAGS 0b10 %define FLAGS 0b10
@@ -195,7 +195,7 @@ section .text
lidt [idt64_descriptor] lidt [idt64_descriptor]
; Finally, we call in to c ; Finally, we call in to c
call kernel_main call kmain
.hang: .hang:
hlt hlt
jmp .hang jmp .hang

View File

@@ -25,7 +25,7 @@ void reverse(char* str, size_t length)
} }
} }
int uitoa(u64 value, char* buffer) int uitoa(uint64_t value, char* buffer)
{ {
int i = 0; int i = 0;
if (value == 0) if (value == 0)
@@ -46,7 +46,7 @@ int uitoa(u64 value, char* buffer)
return i; return i;
} }
int itoa(i64 value, char* buffer) int itoa(int64_t value, char* buffer)
{ {
int i = 0; int i = 0;
@@ -58,16 +58,16 @@ int itoa(i64 value, char* buffer)
} }
bool negative = false; bool negative = false;
u64 v; uint64_t v;
if (value < 0) if (value < 0)
{ {
negative = true; negative = true;
v = (u64)(-value); v = (uint64_t)(-value);
} }
else else
{ {
v = (u64)value; v = (uint64_t)value;
} }
while (v > 0) while (v > 0)

View File

@@ -1,8 +1,9 @@
#pragma once #pragma once
#include "typedef.h" #include <stdint.h>
#include <stddef.h>
int strcmp(const char* a, const char* b); int strcmp(const char* a, const char* b);
void reverse(char* str, size_t length); void reverse(char* str, size_t length);
int uitoa(u64 value, char* buffer); int uitoa(uint64_t value, char* buffer);
int itoa(i64 value, char* buffer); int itoa(int64_t value, char* buffer);

View File

@@ -1,16 +0,0 @@
#pragma once
typedef unsigned char u8;
typedef signed char i8;
typedef unsigned short u16;
typedef signed short i16;
typedef unsigned int u32;
typedef signed int i32;
typedef unsigned long long u64;
typedef signed long long i64;
typedef u64 size_t;
typedef u64 uintptr_t;

View File

@@ -1,13 +1,15 @@
#pragma once #pragma once
static inline void outb(u16 port, u8 val) #include <stdint.h>
static inline void outb(uint16_t port, uint8_t val)
{ {
__asm__ volatile("outb %0, %1" : : "a"(val), "Nd"(port)); __asm__ volatile("outb %0, %1" : : "a"(val), "Nd"(port));
} }
static inline u8 inb(u16 port) static inline uint8_t inb(uint16_t port)
{ {
u8 ret; uint8_t ret;
__asm__ volatile("inb %1, %0" : "=a"(ret) : "Nd"(port)); __asm__ volatile("inb %1, %0" : "=a"(ret) : "Nd"(port));
return ret; return ret;
} }

112
src/vga.c
View File

@@ -1,57 +1,20 @@
#include "vga.h" #include "vga.h"
#include "string.h" #include <stddef.h>
#define ROWS 25 #define ROWS 25
#define COLUMNS 80 #define COLUMNS 80
typedef struct typedef struct
{ {
u8 character; uint8_t character;
u8 color; uint8_t color;
} vga_char; } vga_char_t;
vga_char* vga_buffer = (vga_char*)0xb8000; static vga_char_t* vga_buffer = (vga_char_t*)0xb8000;
u8 cursor_row = 0; static uint8_t cursor_row = 0;
u8 cursor_col = 0; static uint8_t cursor_col = 0;
void vga_set_char(u8 row, u8 col, vga_char character) void vga_put_char(char character, uint8_t color)
{
vga_buffer[COLUMNS * row + col] = character;
}
vga_char vga_char_at(u8 row, u8 col)
{
return vga_buffer[COLUMNS * row + col];
}
void vga_clear()
{
for (u8 row = 0; row < ROWS; row++)
{
for (u8 col = 0; col < COLUMNS; col++)
{
vga_char character = {
.character = ' ',
.color = vga_default_color(),
};
vga_set_char(row, col, character);
}
}
cursor_row = 0;
cursor_col = 0;
}
void vga_set_cursor_position(u8 row, u8 col)
{
if (row < ROWS && col < COLUMNS)
{
cursor_row = row;
cursor_col = col;
}
}
void vga_print_char_colored(char character, vga_color_t color)
{ {
switch (character) switch (character)
{ {
@@ -68,17 +31,16 @@ void vga_print_char_colored(char character, vga_color_t color)
} }
case '\t': case '\t':
{ {
u8 remainter = cursor_col % 4; uint8_t remainter = cursor_col % 4;
cursor_col += remainter == 0 ? 4 : remainter; cursor_col += remainter == 0 ? 4 : remainter;
break; break;
} }
default: default:
{ {
vga_char c = { vga_buffer[COLUMNS * cursor_row + cursor_col] = (vga_char_t){
.character = character, .character = character,
.color = color, .color = color,
}; };
vga_set_char(cursor_row, cursor_col, c);
cursor_col += 1; cursor_col += 1;
break; break;
} }
@@ -92,59 +54,39 @@ void vga_print_char_colored(char character, vga_color_t color)
if (cursor_row >= ROWS) if (cursor_row >= ROWS)
{ {
for (u8 row = 1; row < ROWS; row++) for (size_t row = 1; row < ROWS; row++)
{ {
for (u8 col = 0; col < COLUMNS; col++) for (size_t col = 0; col < COLUMNS; col++)
{ {
vga_set_char(row - 1, col, vga_char_at(row, col)); vga_buffer[COLUMNS * row - 1 + col] = vga_buffer[COLUMNS * row + col];
} }
} }
for (u8 col = 0; col < COLUMNS; col++) for (size_t col = 0; col < COLUMNS; col++)
{ {
vga_char c = { vga_buffer[ROWS - 1 + col] = (vga_char_t){
.character = ' ', .character = ' ',
.color = vga_default_color(), .color = VGA_LIGHT_GRAY | VGA_BLACK << 4,
}; };
vga_set_char(ROWS - 1, col, c);
}; };
cursor_row = ROWS - 1; cursor_row = ROWS - 1;
} }
} }
void vga_print_colored(const char* string, vga_color_t color) void vga_clear()
{ {
for (u8 i = 0; string[i] != '\0'; i++) for (size_t row = 0; row < ROWS; row++)
{ {
vga_print_char_colored(string[i], color); for (size_t col = 0; col < COLUMNS; col++)
{
vga_buffer[COLUMNS * row - 1 + col] = (vga_char_t){
.character = ' ',
.color = VGA_LIGHT_GRAY | VGA_BLACK << 4,
};
}
} }
}
void vga_print_success() cursor_row = 0;
{ cursor_col = 0;
vga_print("[ ");
vga_print_colored("success", VGA_GREEN);
vga_print(" ]");
}
void vga_print_error()
{
vga_print("[ ");
vga_print_colored("error", VGA_RED);
vga_print(" ]");
}
void vga_print_uint(u32 value)
{
char buffer[11];
uitoa(value, buffer);
vga_print(buffer);
}
void vga_print_int(i32 value)
{
char buffer[12];
itoa(value, buffer);
vga_print(buffer);
} }

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include "typedef.h" #include <stdint.h>
#define VGA_BLACK 0 #define VGA_BLACK 0
#define VGA_BLUE 1 #define VGA_BLUE 1
@@ -19,36 +19,5 @@
#define VGA_YELLOW 14 #define VGA_YELLOW 14
#define VGA_WHITE 15 #define VGA_WHITE 15
typedef u8 vga_color_t; void vga_put_char(char character, uint8_t color);
void vga_clear(); void vga_clear();
void vga_set_cursor_position(u8 row, u8 col);
void vga_print_char_colored(char character, vga_color_t color);
void vga_print_colored(const char* string, vga_color_t color);
void vga_print_success();
void vga_print_error();
void vga_print_uint(u32 value);
void vga_print_int(i32 value);
static inline vga_color_t vga_color(vga_color_t fg_color, vga_color_t bg_color)
{
return fg_color | bg_color << 4;
}
static inline vga_color_t vga_default_color()
{
return vga_color(VGA_LIGHT_GRAY, VGA_BLACK);
}
static inline void vga_print_char(char character)
{
vga_print_char_colored(character, vga_default_color());
}
static inline void vga_print(const char* string)
{
vga_print_colored(string, vga_default_color());
}