This commit is contained in:
nub31
2025-08-31 21:27:08 +02:00
parent 68f00d12fe
commit 365ad14122
14 changed files with 232 additions and 110 deletions

View File

@@ -6,8 +6,8 @@ CFLAGS = -m64 -ffreestanding -fno-builtin -Wall -Wextra -Wshadow -std=c23 -g
LDFLAGS = -g
ASFLAGS = -f elf64 -g -F dwarf
SRC_C := src/kernel.c src/string.c src/vga.c
SRC_ASM := src/boot.asm
SRC_C := src/kernel.c src/string.c src/vga.c src/idt.c src/keyboard.c
SRC_ASM := src/boot.asm src/idt_stub.asm
OBJ_C := $(SRC_C:src/%.c=.build/%.o)
OBJ_ASM := $(SRC_ASM:src/%.asm=.build/%.o)

View File

@@ -1,8 +1,5 @@
#include "idt.h"
#include "vga.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#define IDT_SIZE 256
@@ -13,19 +10,19 @@
typedef struct
{
uint16_t address_low;
uint16_t selector;
uint8_t ist;
uint8_t flags;
uint16_t address_mid;
uint32_t address_high;
uint32_t reserved;
u16 address_low;
u16 selector;
u8 ist;
u8 flags;
u16 address_mid;
u32 address_high;
u32 reserved;
} __attribute__((packed)) interrupt_descriptor;
typedef struct
{
uint16_t limit;
uint64_t base;
u16 limit;
u64 base;
} __attribute__((packed)) idtr_t;
extern void* isr_stub_table[];
@@ -70,7 +67,7 @@ static interrupt_descriptor idt[IDT_SIZE];
static void pic_remap(int offset1, int offset2)
{
uint8_t a1, a2;
u8 a1, a2;
a1 = inb(PIC1_DATA);
a2 = inb(PIC2_DATA);
@@ -91,7 +88,7 @@ static void pic_remap(int offset1, int offset2)
outb(PIC2_DATA, a2);
}
static void pic_send_eoi(uint8_t irq)
static void pic_send_eoi(u8 irq)
{
if (irq >= 8)
{
@@ -101,18 +98,18 @@ static void pic_send_eoi(uint8_t irq)
outb(PIC1_COMMAND, 0x20);
}
void register_irq_handler(uint8_t irq, irq_handler_t handler)
void register_irq_handler(u8 irq, irq_handler_t handler)
{
irq_handlers[irq] = handler;
}
static inline void idt_set_descriptor(uint8_t vector, void* handler, uint8_t dpl)
static inline void idt_set_descriptor(u8 vector, void* handler, u8 dpl)
{
interrupt_descriptor* entry = &idt[vector];
entry->address_low = (uint64_t)handler & 0xFFFF;
entry->address_mid = ((uint64_t)handler >> 16) & 0xFFFF;
entry->address_high = (uint64_t)handler >> 32;
entry->address_low = (u64)handler & 0xFFFF;
entry->address_mid = ((u64)handler >> 16) & 0xFFFF;
entry->address_high = (u64)handler >> 32;
entry->selector = 0x08;
entry->flags = 0b1110 | ((dpl & 0b11) << 5) | (1 << 7);
entry->ist = 0;
@@ -130,7 +127,7 @@ void init_idt(void)
idtr_t idtr = {
.base = (uintptr_t)&idt[0],
.limit = (uint16_t)sizeof(interrupt_descriptor) * IDT_SIZE - 1,
.limit = (u16)sizeof(interrupt_descriptor) * IDT_SIZE - 1,
};
__asm__ volatile("lidt %0" : : "m"(idtr));
@@ -155,7 +152,7 @@ void handle_isr(isr_frame_t* frame)
}
else if (frame->int_no < 48)
{
uint8_t irq = frame->int_no - 32;
u8 irq = frame->int_no - 32;
if (irq_handlers[irq])
{

View File

@@ -1,30 +1,30 @@
#pragma once
#include <stdint.h>
#include "typedef.h"
typedef struct
{
uint64_t r15, r14, r13, r12, r11, r10, r9, r8;
uint64_t rbp, rdi, rsi, rdx, rcx, rbx, rax;
uint64_t int_no;
uint64_t err_code;
uint64_t rip, cs, rflags, rsp, ss;
u64 r15, r14, r13, r12, r11, r10, r9, r8;
u64 rbp, rdi, rsi, rdx, rcx, rbx, rax;
u64 int_no;
u64 err_code;
u64 rip, cs, rflags, rsp, ss;
} __attribute__((packed)) isr_frame_t;
typedef void (*irq_handler_t)(const isr_frame_t*);
void init_idt(void);
static inline void outb(uint16_t port, uint8_t val)
static inline void outb(u16 port, u8 val)
{
__asm__ volatile("outb %0, %1" : : "a"(val), "Nd"(port));
}
static inline uint8_t inb(uint16_t port)
static inline u8 inb(u16 port)
{
uint8_t ret;
u8 ret;
__asm__ volatile("inb %1, %0" : "=a"(ret) : "Nd"(port));
return ret;
}
void register_irq_handler(uint8_t irq, irq_handler_t handler);
void register_irq_handler(u8 irq, irq_handler_t handler);

109
src/idt_stub.asm Normal file
View File

@@ -0,0 +1,109 @@
extern handle_isr
isr_common:
push rax
push rbx
push rcx
push rdx
push rsi
push rdi
push rbp
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
mov rdi, rsp
call handle_isr
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rbp
pop rdi
pop rsi
pop rdx
pop rcx
pop rbx
pop rax
add rsp, 16
iretq
%macro ISR_NOERR 1
isr_stub_%1:
push qword 0
push qword %1
jmp isr_common
%endmacro
%macro ISR_ERR 1
isr_stub_%1:
push qword %1
jmp isr_common
%endmacro
; CPU exceptions 0-31
ISR_NOERR 0
ISR_NOERR 1
ISR_NOERR 2
ISR_NOERR 3
ISR_NOERR 4
ISR_NOERR 5
ISR_NOERR 6
ISR_NOERR 7
ISR_ERR 8
ISR_NOERR 9
ISR_ERR 10
ISR_ERR 11
ISR_ERR 12
ISR_ERR 13
ISR_ERR 14
ISR_NOERR 15
ISR_NOERR 16
ISR_ERR 17
ISR_NOERR 18
ISR_NOERR 19
ISR_NOERR 20
ISR_NOERR 21
ISR_NOERR 22
ISR_NOERR 23
ISR_NOERR 24
ISR_NOERR 25
ISR_NOERR 26
ISR_NOERR 27
ISR_NOERR 28
ISR_NOERR 29
ISR_ERR 30
ISR_NOERR 31
%macro GENERATE_ISRS 2
%assign i %1
%rep (%2 - %1 + 1)
ISR_NOERR i
%assign i i+1
%endrep
%endmacro
GENERATE_ISRS 32, 255
%macro GENERATE_ISR_TABLE 2
%assign i %1
%rep (%2 - %1 + 1)
dq isr_stub_%[i]
%assign i i+1
%endrep
%endmacro
global isr_stub_table
isr_stub_table:
GENERATE_ISR_TABLE 0, 255

View File

@@ -1,15 +1,22 @@
#include "kernel.h"
#include "multiboot.h"
#include "idt.h"
#include "keyboard.h"
#include "vga.h"
#include <stdbool.h>
#include <stdint.h>
void kernel_main(multiboot_info_t* multiboot_info)
void kernel_main()
{
vga_clear();
vga_print_success();
vga_print(" VGA intialzied\n");
init_idt();
vga_print_success();
vga_print(" IDT intialzied\n");
init_keyboard();
vga_print_success();
vga_print(" Keyboard intialzied\n");
vga_print("\nWelcome to nub OS\n");
while (true)

View File

@@ -1,3 +1,3 @@
#pragma once
void kernel_panic();
void kernel_panic();

View File

@@ -2,8 +2,6 @@
#include "idt.h"
#include "kernel.h"
#include "vga.h"
#include <stdbool.h>
#include <stdint.h>
#define SCANCODE_LEFT_SHIFT 42
#define SCANCODE_RIGHT_SHIFT 54
@@ -34,7 +32,7 @@ bool caps_lock = false;
static keyboard_handler_t keyboard_handlers[KEYBOARD_HANDLERS_LENGTH];
static int handler_index = 0;
char scan_code_to_ascii(uint8_t scan_code)
char scan_code_to_ascii(u8 scan_code)
{
if (scan_code >= 128)
{
@@ -53,8 +51,8 @@ char scan_code_to_ascii(uint8_t scan_code)
void handle_keyboard(const isr_frame_t* frame)
{
uint8_t code = inb(0x60);
uint8_t scan_code = code & 0x7F;
u8 code = inb(0x60);
u8 scan_code = code & 0x7F;
bool pressed = (code & 0x80) == 0;
switch (scan_code)

View File

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

View File

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

View File

@@ -1,5 +1,4 @@
#include "string.h"
#include <stdbool.h>
int strcmp(const char* a, const char* b)
{
@@ -26,7 +25,7 @@ void reverse(char* str, size_t length)
}
}
int uitoa(uint32_t value, char* buffer)
int uitoa(u64 value, char* buffer)
{
int i = 0;
if (value == 0)
@@ -47,7 +46,7 @@ int uitoa(uint32_t value, char* buffer)
return i;
}
int itoa(int32_t value, char* buffer)
int itoa(i64 value, char* buffer)
{
int i = 0;
@@ -59,16 +58,16 @@ int itoa(int32_t value, char* buffer)
}
bool negative = false;
uint32_t v;
u64 v;
if (value < 0)
{
negative = true;
v = (uint32_t)(-value);
v = (u64)(-value);
}
else
{
v = (uint32_t)value;
v = (u64)value;
}
while (v > 0)

View File

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

16
src/typedef.h Normal file
View File

@@ -0,0 +1,16 @@
#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,37 +1,34 @@
#include "vga.h"
#include "string.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#define ROWS 25
#define COLUMNS 80
typedef struct
{
uint8_t character;
uint8_t color;
u8 character;
u8 color;
} vga_char;
vga_char* vga_buffer = (vga_char*)0xb8000;
uint8_t cursor_row = 0;
uint8_t cursor_col = 0;
u8 cursor_row = 0;
u8 cursor_col = 0;
void vga_set_char(uint8_t row, uint8_t col, vga_char character)
void vga_set_char(u8 row, u8 col, vga_char character)
{
vga_buffer[COLUMNS * row + col] = character;
}
vga_char vga_char_at(uint8_t row, uint8_t col)
vga_char vga_char_at(u8 row, u8 col)
{
return vga_buffer[COLUMNS * row + col];
}
void vga_clear(void)
{
for (uint8_t row = 0; row < ROWS; row++)
for (u8 row = 0; row < ROWS; row++)
{
for (uint8_t col = 0; col < COLUMNS; col++)
for (u8 col = 0; col < COLUMNS; col++)
{
vga_char character = {
.character = ' ',
@@ -45,7 +42,7 @@ void vga_clear(void)
cursor_col = 0;
}
void vga_set_cursor_position(uint8_t row, uint8_t col)
void vga_set_cursor_position(u8 row, u8 col)
{
if (row < ROWS && col < COLUMNS)
{
@@ -71,7 +68,7 @@ void vga_print_char_colored(char character, vga_color_t color)
}
case '\t':
{
uint8_t remainter = cursor_col % 4;
u8 remainter = cursor_col % 4;
cursor_col += remainter == 0 ? 4 : remainter;
break;
}
@@ -95,15 +92,15 @@ void vga_print_char_colored(char character, vga_color_t color)
if (cursor_row >= ROWS)
{
for (uint8_t row = 1; row < ROWS; row++)
for (u8 row = 1; row < ROWS; row++)
{
for (uint8_t col = 0; col < COLUMNS; col++)
for (u8 col = 0; col < COLUMNS; col++)
{
vga_set_char(row - 1, col, vga_char_at(row, col));
}
}
for (uint8_t col = 0; col < COLUMNS; col++)
for (u8 col = 0; col < COLUMNS; col++)
{
vga_char c = {
.character = ' ',
@@ -118,7 +115,7 @@ void vga_print_char_colored(char character, vga_color_t color)
void vga_print_colored(const char* string, vga_color_t color)
{
for (uint8_t i = 0; string[i] != '\0'; i++)
for (u8 i = 0; string[i] != '\0'; i++)
{
vga_print_char_colored(string[i], color);
}
@@ -138,14 +135,14 @@ void vga_print_error(void)
vga_print(" ]");
}
void vga_print_uint(uint32_t value)
void vga_print_uint(u32 value)
{
char buffer[11];
uitoa(value, buffer);
vga_print(buffer);
}
void vga_print_int(int32_t value)
void vga_print_int(i32 value)
{
char buffer[12];
itoa(value, buffer);

View File

@@ -1,6 +1,6 @@
#pragma once
#include <stdint.h>
#include "typedef.h"
#define VGA_BLACK 0
#define VGA_BLUE 1
@@ -19,10 +19,10 @@
#define VGA_YELLOW 14
#define VGA_WHITE 15
typedef uint8_t vga_color_t;
typedef u8 vga_color_t;
void vga_clear(void);
void vga_set_cursor_position(uint8_t row, uint8_t col);
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);
@@ -30,8 +30,8 @@ void vga_print_colored(const char* string, vga_color_t color);
void vga_print_success(void);
void vga_print_error(void);
void vga_print_uint(uint32_t value);
void vga_print_int(int32_t value);
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)
{