...
This commit is contained in:
16
makefile
16
makefile
@@ -17,8 +17,8 @@ build-dir:
|
|||||||
cp .build/kernel.bin .build/iso/boot/
|
cp .build/kernel.bin .build/iso/boot/
|
||||||
grub-mkrescue -o .build/nub-os.iso .build/iso/
|
grub-mkrescue -o .build/nub-os.iso .build/iso/
|
||||||
|
|
||||||
.build/kernel.bin: build-dir .build/boot.o .build/kernel.o .build/print.o
|
.build/kernel.bin: build-dir .build/boot.o .build/kernel.o .build/print.o .build/idt.o .build/keyboard.o .build/exceptions.o .build/interrupts.o
|
||||||
$(LD) -Ttext 0x100000 -o .build/kernel.bin .build/boot.o .build/kernel.o .build/print.o
|
$(LD) -Ttext 0x100000 -o .build/kernel.bin .build/boot.o .build/kernel.o .build/print.o .build/idt.o .build/keyboard.o .build/exceptions.o .build/interrupts.o
|
||||||
|
|
||||||
.build/kernel.o: build-dir src/kernel.c
|
.build/kernel.o: build-dir src/kernel.c
|
||||||
$(CC) $(CFLAGS) -c -o .build/kernel.o src/kernel.c
|
$(CC) $(CFLAGS) -c -o .build/kernel.o src/kernel.c
|
||||||
@@ -26,5 +26,17 @@ build-dir:
|
|||||||
.build/print.o: build-dir src/print.c
|
.build/print.o: build-dir src/print.c
|
||||||
$(CC) $(CFLAGS) -c -o .build/print.o src/print.c
|
$(CC) $(CFLAGS) -c -o .build/print.o src/print.c
|
||||||
|
|
||||||
|
.build/idt.o: build-dir src/idt.c
|
||||||
|
$(CC) $(CFLAGS) -c -o .build/idt.o src/idt.c
|
||||||
|
|
||||||
|
.build/keyboard.o: build-dir src/keyboard.c
|
||||||
|
$(CC) $(CFLAGS) -c -o .build/keyboard.o src/keyboard.c
|
||||||
|
|
||||||
|
.build/exceptions.o: build-dir src/exceptions.c
|
||||||
|
$(CC) $(CFLAGS) -c -o .build/exceptions.o src/exceptions.c
|
||||||
|
|
||||||
|
.build/interrupts.o: build-dir src/interrupts.asm
|
||||||
|
nasm -f elf64 -o .build/interrupts.o src/interrupts.asm
|
||||||
|
|
||||||
.build/boot.o: build-dir src/boot.asm
|
.build/boot.o: build-dir src/boot.asm
|
||||||
nasm -f elf64 -o .build/boot.o src/boot.asm
|
nasm -f elf64 -o .build/boot.o src/boot.asm
|
||||||
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"
|
#include "print.h"
|
||||||
|
|
||||||
void kernel_main(void)
|
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_START 0xb8000
|
||||||
#define BUF_END (BUF_START + BUF_SIZE)
|
#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
|
typedef struct
|
||||||
{
|
{
|
||||||
uint8_t character;
|
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')
|
if (c == '\n')
|
||||||
{
|
{
|
||||||
@@ -75,6 +43,7 @@ void put_char(char c, uint8_t color)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
uint8_t color = fg_color | bg_color << 4;
|
||||||
vga_buffer[cursor_row * COLUMNS + cursor_col] = (vga_char){ c, color };
|
vga_buffer[cursor_row * COLUMNS + cursor_col] = (vga_char){ c, color };
|
||||||
cursor_col++;
|
cursor_col++;
|
||||||
}
|
}
|
||||||
@@ -94,11 +63,14 @@ void put_char(char c, uint8_t color)
|
|||||||
|
|
||||||
void print(const char* string)
|
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++)
|
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>
|
#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(const char* string);
|
||||||
|
void print_clr(const char* string, FG_COLOR fg_color, BG_COLOR bg_color);
|
||||||
void clear_screen(void);
|
void clear_screen(void);
|
||||||
void set_cursor_position(int row, int col);
|
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