...
This commit is contained in:
30
src/exceptions.c
Normal file
30
src/exceptions.c
Normal file
@@ -0,0 +1,30 @@
|
||||
#include "print.h"
|
||||
#include <stdint.h>
|
||||
|
||||
void exception_handler(uint64_t* stack)
|
||||
{
|
||||
uint64_t interrupt_num = stack[0];
|
||||
uint64_t error_code = stack[1];
|
||||
|
||||
print("EXCEPTION: ");
|
||||
if (interrupt_num == 0)
|
||||
{
|
||||
print("Division by zero");
|
||||
}
|
||||
else if (interrupt_num == 13)
|
||||
{
|
||||
print("General protection fault");
|
||||
}
|
||||
else
|
||||
{
|
||||
print("Unknown exception");
|
||||
}
|
||||
print("\nError code: ");
|
||||
// You'd need to implement number printing here
|
||||
print("\nSystem halted.\n");
|
||||
|
||||
while (1)
|
||||
{
|
||||
__asm__ volatile("hlt");
|
||||
}
|
||||
}
|
||||
59
src/idt.c
Normal file
59
src/idt.c
Normal file
@@ -0,0 +1,59 @@
|
||||
#include "idt.h"
|
||||
#include "print.h"
|
||||
|
||||
#define IDT_ENTRIES 256
|
||||
|
||||
struct idt_entry
|
||||
{
|
||||
uint16_t offset_low;
|
||||
uint16_t selector;
|
||||
uint8_t ist;
|
||||
uint8_t type_attr;
|
||||
uint16_t offset_mid;
|
||||
uint32_t offset_high;
|
||||
uint32_t zero;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct idt_ptr
|
||||
{
|
||||
uint16_t limit;
|
||||
uint64_t base;
|
||||
} __attribute__((packed));
|
||||
|
||||
static struct idt_entry idt[IDT_ENTRIES];
|
||||
static struct idt_ptr idt_pointer;
|
||||
|
||||
extern void isr0(void);
|
||||
extern void isr13(void);
|
||||
extern void keyboard_handler_asm(void);
|
||||
|
||||
static void idt_set_gate(uint8_t num, uint64_t handler, uint16_t sel, uint8_t flags)
|
||||
{
|
||||
idt[num].offset_low = handler & 0xFFFF;
|
||||
idt[num].selector = sel;
|
||||
idt[num].ist = 0;
|
||||
idt[num].type_attr = flags;
|
||||
idt[num].offset_mid = (handler >> 16) & 0xFFFF;
|
||||
idt[num].offset_high = (handler >> 32) & 0xFFFFFFFF;
|
||||
idt[num].zero = 0;
|
||||
}
|
||||
|
||||
void idt_init(void)
|
||||
{
|
||||
idt_pointer.limit = (sizeof(struct idt_entry) * IDT_ENTRIES) - 1;
|
||||
idt_pointer.base = (uint64_t)&idt;
|
||||
|
||||
for (int i = 0; i < IDT_ENTRIES; i++)
|
||||
{
|
||||
idt_set_gate(i, 0, 0, 0);
|
||||
}
|
||||
|
||||
idt_set_gate(0, (uint64_t)isr0, 0x08, 0x8E);
|
||||
idt_set_gate(13, (uint64_t)isr13, 0x08, 0x8E);
|
||||
idt_set_gate(33, (uint64_t)keyboard_handler_asm, 0x08, 0x8E);
|
||||
|
||||
__asm__ volatile("lidt %0" : : "m"(idt_pointer));
|
||||
|
||||
print_clr("[success]", FG_GREEN, BG_BLACK);
|
||||
print(" idt initialized\n");
|
||||
}
|
||||
96
src/interrupts.asm
Normal file
96
src/interrupts.asm
Normal file
@@ -0,0 +1,96 @@
|
||||
section .text
|
||||
|
||||
global isr0
|
||||
global isr13
|
||||
global keyboard_handler_asm
|
||||
|
||||
extern exception_handler
|
||||
extern keyboard_handler
|
||||
|
||||
isr0:
|
||||
push 0
|
||||
push 0
|
||||
jmp exception_common
|
||||
|
||||
isr13:
|
||||
push 13
|
||||
jmp exception_common
|
||||
|
||||
exception_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 exception_handler
|
||||
|
||||
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
|
||||
|
||||
keyboard_handler_asm:
|
||||
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
|
||||
|
||||
call keyboard_handler
|
||||
|
||||
mov al, 0x20
|
||||
out 0x20, al
|
||||
|
||||
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
|
||||
|
||||
iretq
|
||||
10
src/kernel.c
10
src/kernel.c
@@ -1,6 +1,12 @@
|
||||
#include "idt.h"
|
||||
#include "keyboard.h"
|
||||
#include "print.h"
|
||||
|
||||
void kernel_main(void)
|
||||
{
|
||||
print("Starting nub-os\n");
|
||||
}
|
||||
idt_init();
|
||||
keyboard_init();
|
||||
|
||||
print("Welcome to nub OS\n");
|
||||
print("> ");
|
||||
}
|
||||
80
src/keyboard.c
Normal file
80
src/keyboard.c
Normal file
@@ -0,0 +1,80 @@
|
||||
#include "print.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define KEYBOARD_DATA_PORT 0x60
|
||||
#define KEYBOARD_STATUS_PORT 0x64
|
||||
|
||||
static char scancode_to_ascii[] = { 0, 0, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b',
|
||||
'\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', 0,
|
||||
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0, '\\', 'z',
|
||||
'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0, '*', 0, ' ' };
|
||||
|
||||
static char input_buffer[256];
|
||||
static int buffer_index = 0;
|
||||
static bool key_available = false;
|
||||
|
||||
static uint8_t inb(uint16_t port)
|
||||
{
|
||||
uint8_t result;
|
||||
__asm__ volatile("inb %1, %0" : "=a"(result) : "Nd"(port));
|
||||
return result;
|
||||
}
|
||||
|
||||
void keyboard_handler(void)
|
||||
{
|
||||
uint8_t scancode = inb(KEYBOARD_DATA_PORT);
|
||||
|
||||
if (scancode & 0x80)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (scancode < sizeof(scancode_to_ascii))
|
||||
{
|
||||
char ascii = scancode_to_ascii[scancode];
|
||||
if (ascii)
|
||||
{
|
||||
if (ascii == '\b')
|
||||
{
|
||||
if (buffer_index > 0)
|
||||
{
|
||||
buffer_index--;
|
||||
print("\b \b");
|
||||
}
|
||||
}
|
||||
else if (ascii == '\n')
|
||||
{
|
||||
input_buffer[buffer_index] = '\0';
|
||||
print("\n");
|
||||
key_available = true;
|
||||
}
|
||||
else if (buffer_index < 255)
|
||||
{
|
||||
input_buffer[buffer_index++] = ascii;
|
||||
char str[2] = { ascii, '\0' };
|
||||
print(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char* keyboard_get_line(void)
|
||||
{
|
||||
buffer_index = 0;
|
||||
key_available = false;
|
||||
|
||||
while (!key_available)
|
||||
{
|
||||
__asm__ volatile("hlt");
|
||||
}
|
||||
|
||||
return input_buffer;
|
||||
}
|
||||
|
||||
void keyboard_init(void)
|
||||
{
|
||||
__asm__ volatile("sti");
|
||||
print_clr("[success]", FG_GREEN, BG_BLACK);
|
||||
print(" keyboard initialized\n");
|
||||
}
|
||||
4
src/keyboard.h
Normal file
4
src/keyboard.h
Normal file
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
void keyboard_init(void);
|
||||
char* keyboard_get_line(void);
|
||||
42
src/print.c
42
src/print.c
@@ -8,38 +8,6 @@
|
||||
#define BUF_START 0xb8000
|
||||
#define BUF_END (BUF_START + BUF_SIZE)
|
||||
|
||||
enum FG_COLOR
|
||||
{
|
||||
FG_BLACK = 0x0,
|
||||
FG_BLUE = 0x1,
|
||||
FG_GREEN = 0x2,
|
||||
FG_CYAN = 0x3,
|
||||
FG_RED = 0x4,
|
||||
FG_MAGENTA = 0x5,
|
||||
FG_BROWN = 0x6,
|
||||
FG_LIGHT_GRAY = 0x7,
|
||||
FG_DARK_GRAY = 0x8,
|
||||
FG_LIGHT_BLUE = 0x9,
|
||||
FG_LIGHT_GREEN = 0xA,
|
||||
FG_LIGHT_CYAN = 0xB,
|
||||
FG_LIGHT_RED = 0xC,
|
||||
FG_LIGHT_MAGENTA = 0xD,
|
||||
FG_YELLOW = 0xE,
|
||||
FG_WHITE = 0xF,
|
||||
};
|
||||
|
||||
enum BG_COLOR
|
||||
{
|
||||
BG_BLACK = 0x0,
|
||||
BG_BLUE = 0x1,
|
||||
BG_GREEN = 0x2,
|
||||
BG_CYAN = 0x3,
|
||||
BG_RED = 0x4,
|
||||
BG_MAGENTA = 0x5,
|
||||
BG_BROWN = 0x6,
|
||||
BG_LIGHT_GRAY = 0x7,
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t character;
|
||||
@@ -66,7 +34,7 @@ void scroll(void)
|
||||
}
|
||||
}
|
||||
|
||||
void put_char(char c, uint8_t color)
|
||||
void put_char(char c, FG_COLOR fg_color, BG_COLOR bg_color)
|
||||
{
|
||||
if (c == '\n')
|
||||
{
|
||||
@@ -75,6 +43,7 @@ void put_char(char c, uint8_t color)
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t color = fg_color | bg_color << 4;
|
||||
vga_buffer[cursor_row * COLUMNS + cursor_col] = (vga_char){ c, color };
|
||||
cursor_col++;
|
||||
}
|
||||
@@ -94,11 +63,14 @@ void put_char(char c, uint8_t color)
|
||||
|
||||
void print(const char* string)
|
||||
{
|
||||
uint8_t color = FG_WHITE | BG_BLACK << 4;
|
||||
print_clr(string, FG_WHITE, BG_BLACK);
|
||||
}
|
||||
|
||||
void print_clr(const char* string, FG_COLOR fg_color, BG_COLOR bg_color)
|
||||
{
|
||||
for (int i = 0; string[i]; i++)
|
||||
{
|
||||
put_char(string[i], color);
|
||||
put_char(string[i], fg_color, bg_color);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
36
src/print.h
36
src/print.h
@@ -1,8 +1,40 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
void kernel_print(const char* string);
|
||||
typedef enum
|
||||
{
|
||||
FG_BLACK = 0x0,
|
||||
FG_BLUE = 0x1,
|
||||
FG_GREEN = 0x2,
|
||||
FG_CYAN = 0x3,
|
||||
FG_RED = 0x4,
|
||||
FG_MAGENTA = 0x5,
|
||||
FG_BROWN = 0x6,
|
||||
FG_LIGHT_GRAY = 0x7,
|
||||
FG_DARK_GRAY = 0x8,
|
||||
FG_LIGHT_BLUE = 0x9,
|
||||
FG_LIGHT_GREEN = 0xA,
|
||||
FG_LIGHT_CYAN = 0xB,
|
||||
FG_LIGHT_RED = 0xC,
|
||||
FG_LIGHT_MAGENTA = 0xD,
|
||||
FG_YELLOW = 0xE,
|
||||
FG_WHITE = 0xF,
|
||||
} FG_COLOR;
|
||||
|
||||
void put_char(char c, uint8_t color);
|
||||
typedef enum
|
||||
{
|
||||
BG_BLACK = 0x0,
|
||||
BG_BLUE = 0x1,
|
||||
BG_GREEN = 0x2,
|
||||
BG_CYAN = 0x3,
|
||||
BG_RED = 0x4,
|
||||
BG_MAGENTA = 0x5,
|
||||
BG_BROWN = 0x6,
|
||||
BG_LIGHT_GRAY = 0x7,
|
||||
} BG_COLOR;
|
||||
|
||||
void put_char(char c, FG_COLOR fg_color, BG_COLOR bg_color);
|
||||
void print(const char* string);
|
||||
void print_clr(const char* string, FG_COLOR fg_color, BG_COLOR bg_color);
|
||||
void clear_screen(void);
|
||||
void set_cursor_position(int row, int col);
|
||||
10
src/string.c
Normal file
10
src/string.c
Normal file
@@ -0,0 +1,10 @@
|
||||
int strcmp(const char* a, const char* b)
|
||||
{
|
||||
while ((*a != '\0' && *b != '\0') && *a == *b)
|
||||
{
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
|
||||
return (*a == *b) ? 0 : (*a > *b) ? 1 : -1;
|
||||
}
|
||||
3
src/string.h
Normal file
3
src/string.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
int strcmp(const char* a, const char* b);
|
||||
Reference in New Issue
Block a user