From 05e1fedcc9cd30d1a34a65e640da45e980b4f859 Mon Sep 17 00:00:00 2001 From: Marvin Borner Date: Thu, 19 Sep 2019 19:56:59 +0200 Subject: Moved source to kernel directory --- build.sh | 8 +- src/boot.asm | 50 ------- src/commands/command.c | 26 ---- src/commands/command.h | 6 - src/gdt/gdt.asm | 14 -- src/gdt/gdt.c | 51 ------- src/gdt/gdt.h | 6 - src/graphics/graphics.h | 21 --- src/graphics/vga.c | 145 ------------------- src/grub.cfg | 6 - src/input/input.h | 10 -- src/input/ps2/keyboard.c | 50 ------- src/input/ps2/mouse.c | 107 -------------- src/interrupts/idt.asm | 6 - src/interrupts/idt.c | 46 ------ src/interrupts/interrupts.h | 30 ---- src/interrupts/irq.asm | 157 --------------------- src/interrupts/irq.c | 109 --------------- src/interrupts/isr.asm | 277 ------------------------------------- src/interrupts/isr.c | 155 --------------------- src/io/io.asm | 10 -- src/io/io.c | 21 --- src/io/io.h | 12 -- src/kernel.c | 32 ----- src/kernel/boot.asm | 50 +++++++ src/kernel/commands/command.c | 26 ++++ src/kernel/commands/command.h | 6 + src/kernel/gdt/gdt.asm | 14 ++ src/kernel/gdt/gdt.c | 51 +++++++ src/kernel/gdt/gdt.h | 6 + src/kernel/graphics/graphics.h | 21 +++ src/kernel/graphics/vga.c | 145 +++++++++++++++++++ src/kernel/grub.cfg | 6 + src/kernel/input/input.h | 10 ++ src/kernel/input/ps2/keyboard.c | 50 +++++++ src/kernel/input/ps2/mouse.c | 107 ++++++++++++++ src/kernel/interrupts/idt.asm | 6 + src/kernel/interrupts/idt.c | 46 ++++++ src/kernel/interrupts/interrupts.h | 30 ++++ src/kernel/interrupts/irq.asm | 157 +++++++++++++++++++++ src/kernel/interrupts/irq.c | 109 +++++++++++++++ src/kernel/interrupts/isr.asm | 277 +++++++++++++++++++++++++++++++++++++ src/kernel/interrupts/isr.c | 155 +++++++++++++++++++++ src/kernel/io/io.asm | 10 ++ src/kernel/io/io.c | 21 +++ src/kernel/io/io.h | 12 ++ src/kernel/kernel.c | 23 +++ src/kernel/lib/lib.h | 18 +++ src/kernel/lib/memory.c | 26 ++++ src/kernel/lib/string.c | 27 ++++ src/kernel/linker.ld | 25 ++++ src/kernel/sound/frequency.c | 31 +++++ src/kernel/sound/sound.h | 6 + src/kernel/timer/timer.c | 32 +++++ src/kernel/timer/timer.h | 8 ++ src/lib/lib.h | 18 --- src/lib/memory.c | 26 ---- src/lib/string.c | 27 ---- src/linker.ld | 25 ---- src/sound/frequency.c | 31 ----- src/sound/sound.h | 6 - src/timer/timer.c | 32 ----- src/timer/timer.h | 8 -- 63 files changed, 1515 insertions(+), 1524 deletions(-) delete mode 100644 src/boot.asm delete mode 100644 src/commands/command.c delete mode 100644 src/commands/command.h delete mode 100644 src/gdt/gdt.asm delete mode 100644 src/gdt/gdt.c delete mode 100644 src/gdt/gdt.h delete mode 100644 src/graphics/graphics.h delete mode 100644 src/graphics/vga.c delete mode 100644 src/grub.cfg delete mode 100644 src/input/input.h delete mode 100644 src/input/ps2/keyboard.c delete mode 100644 src/input/ps2/mouse.c delete mode 100644 src/interrupts/idt.asm delete mode 100644 src/interrupts/idt.c delete mode 100644 src/interrupts/interrupts.h delete mode 100644 src/interrupts/irq.asm delete mode 100644 src/interrupts/irq.c delete mode 100644 src/interrupts/isr.asm delete mode 100644 src/interrupts/isr.c delete mode 100644 src/io/io.asm delete mode 100644 src/io/io.c delete mode 100644 src/io/io.h delete mode 100644 src/kernel.c create mode 100644 src/kernel/boot.asm create mode 100644 src/kernel/commands/command.c create mode 100644 src/kernel/commands/command.h create mode 100644 src/kernel/gdt/gdt.asm create mode 100644 src/kernel/gdt/gdt.c create mode 100644 src/kernel/gdt/gdt.h create mode 100644 src/kernel/graphics/graphics.h create mode 100644 src/kernel/graphics/vga.c create mode 100644 src/kernel/grub.cfg create mode 100644 src/kernel/input/input.h create mode 100644 src/kernel/input/ps2/keyboard.c create mode 100644 src/kernel/input/ps2/mouse.c create mode 100644 src/kernel/interrupts/idt.asm create mode 100644 src/kernel/interrupts/idt.c create mode 100644 src/kernel/interrupts/interrupts.h create mode 100644 src/kernel/interrupts/irq.asm create mode 100644 src/kernel/interrupts/irq.c create mode 100644 src/kernel/interrupts/isr.asm create mode 100644 src/kernel/interrupts/isr.c create mode 100644 src/kernel/io/io.asm create mode 100644 src/kernel/io/io.c create mode 100644 src/kernel/io/io.h create mode 100644 src/kernel/kernel.c create mode 100644 src/kernel/lib/lib.h create mode 100644 src/kernel/lib/memory.c create mode 100644 src/kernel/lib/string.c create mode 100644 src/kernel/linker.ld create mode 100644 src/kernel/sound/frequency.c create mode 100644 src/kernel/sound/sound.h create mode 100644 src/kernel/timer/timer.c create mode 100644 src/kernel/timer/timer.h delete mode 100644 src/lib/lib.h delete mode 100644 src/lib/memory.c delete mode 100644 src/lib/string.c delete mode 100644 src/linker.ld delete mode 100644 src/sound/frequency.c delete mode 100644 src/sound/sound.h delete mode 100644 src/timer/timer.c delete mode 100644 src/timer/timer.h diff --git a/build.sh b/build.sh index 031abc9..1c7de3c 100755 --- a/build.sh +++ b/build.sh @@ -9,11 +9,11 @@ rm -rf ./build/ ./iso/ mkdir ./build/ # Assemble ASM files -nasm -f elf ./src/boot.asm -o ./build/boot.o +nasm -f elf ./src/kernel/boot.asm -o ./build/boot.o # Make all C files files="" -find ./src -name \*.c >./build/tmp +find ./src/kernel/ -name \*.c >./build/tmp while read -r line; do stripped=$(echo "${line}" | sed -r 's/\//_/g') stripped=${stripped#??????} @@ -25,7 +25,7 @@ rm ./build/tmp # shellcheck disable=SC2086 # Shellcheck suppression is needed because gcc would think that $files is one file -i686-elf-gcc -T ./src/linker.ld -o ./build/melvix.bin -ffreestanding -O2 -nostdlib ./build/boot.o $files -lgcc +i686-elf-gcc -T ./src/kernel/linker.ld -o ./build/melvix.bin -ffreestanding -O2 -nostdlib ./build/boot.o $files -lgcc # Testing if grub-file --is-x86-multiboot ./build/melvix.bin; then @@ -38,7 +38,7 @@ fi # Create ISO mkdir -p ./iso/boot/grub cp ./build/melvix.bin ./iso/boot/ -cp ./src/grub.cfg ./iso/boot/grub/ +cp ./src/kernel/grub.cfg ./iso/boot/grub/ grub-mkrescue -o ./build/melvix.iso ./iso/ # Run ISO diff --git a/src/boot.asm b/src/boot.asm deleted file mode 100644 index 0581eb6..0000000 --- a/src/boot.asm +++ /dev/null @@ -1,50 +0,0 @@ -[BITS 32] -global start -start: - mov esp, _sys_stack ; Points stack to stack area - jmp stublet - -; Align with 4 Bytes -ALIGN 4 -mboot: - ; Multiboot macros - MULTIBOOT_PAGE_ALIGN equ 1<<0 - MULTIBOOT_MEMORY_INFO equ 1<<1 - MULTIBOOT_AOUT_KLUDGE equ 1<<16 - MULTIBOOT_HEADER_MAGIC equ 0x1BADB002 - MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO | MULTIBOOT_AOUT_KLUDGE - MULTIBOOT_CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) - EXTERN code, bss, end - - ; GRUB Multiboot header - dd MULTIBOOT_HEADER_MAGIC - dd MULTIBOOT_HEADER_FLAGS - dd MULTIBOOT_CHECKSUM - - ; AOUT kludge - dd mboot - dd code - dd bss - dd end - dd start - -; Endless loop -stublet: - extern kernel_main - call kernel_main - jmp $ - -%include "src/gdt/gdt.asm" - -%include "src/interrupts/idt.asm" - -%include "src/interrupts/isr.asm" - -%include "src/interrupts/irq.asm" - -%include "src/io/io.asm" - -; Store the stack -SECTION .bss - resb 8192 ; Reserve 8KiB -_sys_stack: \ No newline at end of file diff --git a/src/commands/command.c b/src/commands/command.c deleted file mode 100644 index 9cbcb07..0000000 --- a/src/commands/command.c +++ /dev/null @@ -1,26 +0,0 @@ -#include "../graphics/graphics.h" -#include "../lib/lib.h" -#include "../io/io.h" - -int32_t starts_with(const char *a, const char *b) { - size_t length_pre = strlen(b); - size_t length_main = strlen(a); - return length_main < length_pre ? 0 : memory_compare(b, a, length_pre) == 0; -} - -extern void shutdown(); - -void exec_command(char *command) { - if (starts_with(command, "ls")) - terminal_write_line("Listing files"); - else if (starts_with(command, "help")) - terminal_write_line("I can't help you write now"); - else if (starts_with(command, "ping")) - terminal_write_line("pong!"); - else if (starts_with(command, "shutdown")) - shutdown(); - else if (starts_with(command, "reboot")) - reboot(); - else - terminal_write_line("Command not found!"); -} diff --git a/src/commands/command.h b/src/commands/command.h deleted file mode 100644 index 2a43416..0000000 --- a/src/commands/command.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef MELVIX_COMMAND_H -#define MELVIX_COMMAND_H - -void exec_command(char *command); - -#endif diff --git a/src/gdt/gdt.asm b/src/gdt/gdt.asm deleted file mode 100644 index c2128e4..0000000 --- a/src/gdt/gdt.asm +++ /dev/null @@ -1,14 +0,0 @@ -; GDT flush function -global gdt_flush -extern gp -gdt_flush: - lgdt [gp] - mov ax, 0x10 ; Data segment offset of GDT - mov ds, ax - mov es, ax - mov fs, ax - mov gs, ax - mov ss, ax - jmp 0x08:flush2 ; Code segment offset -flush2: - ret ; Returns to C code \ No newline at end of file diff --git a/src/gdt/gdt.c b/src/gdt/gdt.c deleted file mode 100644 index 813b432..0000000 --- a/src/gdt/gdt.c +++ /dev/null @@ -1,51 +0,0 @@ -struct gdt_entry { - unsigned short limit_low; - unsigned short base_low; - unsigned char base_middle; - unsigned char access; - unsigned char granularity; - unsigned char base_high; -} __attribute__((packed)); - -struct gdt_ptr { - unsigned short limit; - unsigned int base; -} __attribute__((packed)); - -struct gdt_entry gdt[3]; -struct gdt_ptr gp; - -extern void gdt_flush(); - -void gdt_set_gate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran) { - // Set descriptor base address - gdt[num].base_low = (base & 0xFFFF); - gdt[num].base_middle = (base >> 16) & 0xFF; - gdt[num].base_high = (base >> 24) & 0xFF; - - // Set descriptor limits - gdt[num].limit_low = (limit & 0xFFFF); - gdt[num].granularity = ((limit >> 16) & 0x0F); - - // Set granularity and access flags - gdt[num].granularity |= (gran & 0xF0); - gdt[num].access = access; -} - -void gdt_install() { - // Set GDT pointer and limit - gp.limit = (sizeof(struct gdt_entry) * 3) - 1; - gp.base = &gdt; - - // NULL descriptor - gdt_set_gate(0, 0, 0, 0, 0); - - // Code segment - gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); - - // Data segment - gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); - - // Remove old GDT and install the new changes! - gdt_flush(); -} \ No newline at end of file diff --git a/src/gdt/gdt.h b/src/gdt/gdt.h deleted file mode 100644 index 46d80e2..0000000 --- a/src/gdt/gdt.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef MELVIX_GDT_H -#define MELVIX_GDT_H - -void gdt_install(); - -#endif diff --git a/src/graphics/graphics.h b/src/graphics/graphics.h deleted file mode 100644 index a9ed917..0000000 --- a/src/graphics/graphics.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MELVIX_VGA_H -#define MELVIX_VGA_H - -#include -#include - -enum vga_color; - -void terminal_initialize(void); - -void terminal_set_color(uint8_t color); - -void terminal_clear(); - -void terminal_write_string(const char *data); - -void terminal_put_char(char c); - -void terminal_write_line(const char *data); - -#endif \ No newline at end of file diff --git a/src/graphics/vga.c b/src/graphics/vga.c deleted file mode 100644 index 86c00ff..0000000 --- a/src/graphics/vga.c +++ /dev/null @@ -1,145 +0,0 @@ -#include -#include -#include "../io/io.h" -#include "../lib/lib.h" -#include "../commands/command.h" -#include "../interrupts/interrupts.h" - -// Hardware text mode color constants -enum vga_color { - VGA_COLOR_BLACK = 0, - VGA_COLOR_BLUE = 1, - VGA_COLOR_GREEN = 2, - VGA_COLOR_CYAN = 3, - VGA_COLOR_RED = 4, - VGA_COLOR_MAGENTA = 5, - VGA_COLOR_BROWN = 6, - VGA_COLOR_LIGHT_GREY = 7, - VGA_COLOR_DARK_GREY = 8, - VGA_COLOR_LIGHT_BLUE = 9, - VGA_COLOR_LIGHT_GREEN = 10, - VGA_COLOR_LIGHT_CYAN = 11, - VGA_COLOR_LIGHT_RED = 12, - VGA_COLOR_LIGHT_MAGENTA = 13, - VGA_COLOR_LIGHT_BROWN = 14, - VGA_COLOR_WHITE = 15, -}; - -static inline uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg) { - return fg | bg << 4; -} - -static inline uint16_t vga_entry(unsigned char uc, uint8_t color) { - return (uint16_t) uc | (uint16_t) color << 8; -} - -static const size_t VGA_WIDTH = 80; -static const size_t VGA_HEIGHT = 25; - -size_t terminal_row; -size_t terminal_column; -uint8_t terminal_color; -uint16_t *terminal_buffer; - -char text[1024] = {0}; - -void terminal_clear() { - for (size_t y = 0; y < VGA_HEIGHT; y++) { - for (size_t x = 0; x < VGA_WIDTH; x++) { - const size_t index = y * VGA_WIDTH + x; - terminal_buffer[index] = vga_entry(' ', terminal_color); - } - } -} - -void terminal_enable_cursor(uint8_t cursor_start, uint8_t cursor_end) { - send(0x3D4, 0x0A); - send(0x3D5, (receive(0x3D5) & 0xC0) | cursor_start); - send(0x3D4, 0x0B); - send(0x3D5, (receive(0x3D5) & 0xE0) | cursor_end); -} - -void terminal_update_cursor(void) { - unsigned temp = terminal_row * VGA_WIDTH + terminal_column; - send(0x3D4, 14); - send(0x3D5, temp >> 8); - send(0x3D4, 15); - send(0x3D5, temp); -} - -void terminal_initialize(void) { - terminal_enable_cursor(0, 15); - terminal_row = 0; - terminal_column = 0; - terminal_color = vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK); - terminal_buffer = (uint16_t *) 0xB8000; - terminal_clear(); -} - -void terminal_scroll(void) { - if (terminal_row >= VGA_HEIGHT) { - terminal_row = VGA_HEIGHT - 1; - for (size_t x = 0; x < VGA_WIDTH; x++) - for (size_t y = 0; y < VGA_HEIGHT; y++) { - uint16_t c = terminal_buffer[y * VGA_WIDTH + x]; - terminal_buffer[(y - 1) * VGA_WIDTH + x] = c; - terminal_buffer[y * VGA_WIDTH + x] = vga_entry(' ', terminal_color); - } - } -} - -void terminal_set_color(uint8_t color) { - terminal_color = color; -} - -void terminal_put_entry_at(char c, uint8_t color, size_t x, size_t y) { - const size_t index = y * VGA_WIDTH + x; - terminal_buffer[index] = vga_entry(c, color); -} - -void terminal_put_char(char c) { - if (c == 0x08) { - if (terminal_column != 0) terminal_column--; - } else if (c == 0x09) { - terminal_column = (terminal_column + 8) & ~(8 - 1); - } else if (c == '\r') { - terminal_column = 0; - } else if (c == '\n') { - if (irq_is_installed(1)) exec_command(text); - memory_set(text, 0, sizeof(text)); - terminal_column = 0; - terminal_row++; - terminal_scroll(); - terminal_put_entry_at('$', terminal_color, terminal_column, terminal_row); - terminal_column = 2; - } else if (c >= ' ') { // Any printable character - strcat(text, &c); - terminal_put_entry_at(c, terminal_color, terminal_column, terminal_row); - terminal_column++; - } - - // Add new line on overflow - if (terminal_column >= VGA_WIDTH) { - terminal_column = 0; - terminal_row++; - } - - terminal_scroll(); - terminal_update_cursor(); -} - -void terminal_write(const char *data, size_t size) { - for (size_t i = 0; i < size; i++) - terminal_put_char(data[i]); -} - -void terminal_write_string(const char *data) { - terminal_write(data, strlen(data)); -} - -void terminal_write_line(const char *data) { - terminal_row++; - terminal_column = 0; - terminal_write_string(data); - terminal_column = 0; -} diff --git a/src/grub.cfg b/src/grub.cfg deleted file mode 100644 index 8106b6c..0000000 --- a/src/grub.cfg +++ /dev/null @@ -1,6 +0,0 @@ -set timeout=0 -set default=0 - -menuentry "Melvix" { - multiboot /boot/melvix.bin -} \ No newline at end of file diff --git a/src/input/input.h b/src/input/input.h deleted file mode 100644 index 60d2f79..0000000 --- a/src/input/input.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef MELVIX_INPUT_H -#define MELVIX_INPUT_H - -void mouse_install(); - -char get_mouse(int n); - -void keyboard_install(); - -#endif diff --git a/src/input/ps2/keyboard.c b/src/input/ps2/keyboard.c deleted file mode 100644 index ae17675..0000000 --- a/src/input/ps2/keyboard.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "../../interrupts/interrupts.h" -#include "../../io/io.h" -#include "../../graphics/graphics.h" - -unsigned char keymap[128] = { - 0 /*E*/, 27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', - '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', - 0 /*C*/, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0 /*LS*/, - '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0 /*RS*/, '*', - 0, // Alt key - ' ', // Space bar - 0, // Caps lock - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // F keys - 0, // Num lock - 0, // Scroll lock - 0, // Home key - 0, // Up arrow - 0, // Page up - '-', - 0, // Left arrow - 0, - 0, // Right arrow - '+', - 0, // End key - 0, // Down arrow - 0, // Page down - 0, // Insert key - 0, // Delete key - 0, 0, 0, - 0, // F11 - 0, // F12 - 0, // Other keys -}; - -void keyboard_handler(struct regs *r) { - unsigned char scan_code; - - scan_code = receive(0x60); - - if (scan_code & 0x80) { - // Release - } else { - terminal_put_char(keymap[scan_code]); - } -} - -/* Installs the keyboard handler into IRQ1 */ -void keyboard_install() { - irq_install_handler(1, keyboard_handler); -} diff --git a/src/input/ps2/mouse.c b/src/input/ps2/mouse.c deleted file mode 100644 index 49c5a6c..0000000 --- a/src/input/ps2/mouse.c +++ /dev/null @@ -1,107 +0,0 @@ -#include "../../io/io.h" -#include "../../interrupts/interrupts.h" - -char mouse_cycle = 0; -signed char mouse_byte[3], mouse_ex[3]; -signed char mouse_x = 0; -signed char mouse_y = 0; -int mouse_but_1 = 0; -int mouse_but_2 = 0; -int mm_n[3] = {0, 0, 0,}; - -void mouse_handler(struct regs *a_r) { - switch (mouse_cycle) { - case 0: - mouse_byte[0] = receive(0x60); - mouse_cycle++; - break; - case 1: - mouse_byte[1] = receive(0x60); - mouse_cycle++; - break; - case 2: - mouse_byte[2] = receive(0x60); - mouse_x = mouse_byte[1]; - mouse_y = mouse_byte[2]; - mouse_but_1 = (mouse_byte[0] % 2); - mouse_but_2 = ((mouse_byte[0] % 4) - (mouse_byte[0] % 2)) / 2; - mouse_cycle = 0; - mouse_ex[0] = mouse_byte[0]; - mm_n[0] = 1; - mouse_ex[1] = mouse_byte[1]; - mm_n[1] = 1; - mouse_ex[2] = mouse_byte[2]; - mm_n[2] = 1; - break; - default: - break; - } -} - -inline void mouse_wait(char a_type) { - unsigned int _time_out = 100000; - if (a_type == 0) { - while (_time_out--) { - if ((receive(0x64) & 1) == 1) { - return; - } - } - return; - } else { - while (_time_out--) { - if ((receive(0x64) & 2) == 0) { - return; - } - } - return; - } -} - -inline void mouse_write(char a_write) { - mouse_wait(1); - send(0x64, 0xD4); - mouse_wait(1); - send(0x60, a_write); -} - -char mouse_read() { - mouse_wait(0); - return receive(0x60); -} - -void mouse_install() { - char _status; - - // Enable auxiliary mouse device - mouse_wait(1); - send(0x64, 0xA8); - - // Enable interrupts - mouse_wait(1); - send(0x64, 0x20); - mouse_wait(0); - _status = (receive(0x60) | 2); - mouse_wait(1); - send(0x64, 0x60); - mouse_wait(1); - send(0x60, _status); - - // Use default settings - mouse_write(0xF6); - mouse_read(); - - // Enable mouse - mouse_write(0xF4); - mouse_read(); - - // Setup the mouse handler - irq_install_handler(2, mouse_handler); -} - -char get_mouse(int n) { - if (mm_n[n] == 1) { - mm_n[n] = 0; - return mouse_ex[n]; - } else - return 0; -} \ No newline at end of file diff --git a/src/interrupts/idt.asm b/src/interrupts/idt.asm deleted file mode 100644 index 90eab47..0000000 --- a/src/interrupts/idt.asm +++ /dev/null @@ -1,6 +0,0 @@ -; IDT loader -global idt_load -extern idtp -idt_load: - lidt [idtp] - ret diff --git a/src/interrupts/idt.c b/src/interrupts/idt.c deleted file mode 100644 index ba71339..0000000 --- a/src/interrupts/idt.c +++ /dev/null @@ -1,46 +0,0 @@ -#include "../lib/lib.h" - -struct idt_entry { - unsigned short base_lo; - unsigned short sel; // Kernel segment - unsigned char always0; // Always 0 - unsigned char flags; - unsigned short base_hi; -} __attribute__((packed)); - -struct idt_ptr { - unsigned short limit; - unsigned int base; -} __attribute__((packed)); - -// Initialize IDT with 256 entries -struct idt_entry idt[256]; -struct idt_ptr idtp; - -// Defined in idt.asm -extern void idt_load(); - -void idt_set_gate(unsigned char num, unsigned long base, unsigned short sel, unsigned char flags) { - // Specify the interrupt routine's base address - idt[num].base_lo = (base & 0xFFFF); - idt[num].base_hi = (base >> 16) & 0xFFFF; - - // Set selector/segment of IDT entry - idt[num].sel = sel; - idt[num].always0 = 0; - idt[num].flags = flags; -} - -// Install IDT -void idt_install() { - // Set IDT pointer and limit - idtp.limit = (sizeof(struct idt_entry) * 256) - 1; - idtp.base = &idt; - - // Clear IDT by setting memory cells to 0 - memory_set(&idt, 0, sizeof(struct idt_entry) * 256); - - // TODO: Add method to add ISRs to IDT - - idt_load(); -} diff --git a/src/interrupts/interrupts.h b/src/interrupts/interrupts.h deleted file mode 100644 index 755a633..0000000 --- a/src/interrupts/interrupts.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef MELVIX_INTERRUPTS_H -#define MELVIX_INTERRUPTS_H - -// IDT -void idt_install(); - -void idt_set_gate(unsigned char num, unsigned long base, unsigned short sel, unsigned char flags); - -// ISRS -void isrs_install(); - -struct regs { - unsigned int gs, fs, es, ds; - unsigned int edi, esi, ebp, esp, ebx, edx, ecx, eax; - unsigned int int_no, err_code; - unsigned int eip, cs, eflags, useresp, ss; -}; - -// IRQ -void irq_install(); - -void irq_install_handler(int irq, void (*handler)(struct regs *r)); - -void irq_uninstall_handler(int irq); - -void irq_handler(struct regs *r); - -int irq_is_installed(int irq); - -#endif diff --git a/src/interrupts/irq.asm b/src/interrupts/irq.asm deleted file mode 100644 index c485613..0000000 --- a/src/interrupts/irq.asm +++ /dev/null @@ -1,157 +0,0 @@ -global irq0 -global irq1 -global irq2 -global irq3 -global irq4 -global irq5 -global irq6 -global irq7 -global irq8 -global irq9 -global irq10 -global irq11 -global irq12 -global irq13 -global irq14 -global irq15 - -; 32: IRQ0 -irq0: - cli - push byte 0 - push byte 32 - jmp irq_common_stub - -; 33: IRQ1 -irq1: - cli - push byte 0 - push byte 33 - jmp irq_common_stub - -; 34: IRQ2 -irq2: - cli - push byte 0 - push byte 34 - jmp irq_common_stub - -; 35: IRQ3 -irq3: - cli - push byte 0 - push byte 35 - jmp irq_common_stub - -; 36: IRQ4 -irq4: - cli - push byte 0 - push byte 36 - jmp irq_common_stub - -; 37: IRQ5 -irq5: - cli - push byte 0 - push byte 37 - jmp irq_common_stub - -; 38: IRQ6 -irq6: - cli - push byte 0 - push byte 38 - jmp irq_common_stub - -; 39: IRQ7 -irq7: - cli - push byte 0 - push byte 39 - jmp irq_common_stub - -; 40: IRQ8 -irq8: - cli - push byte 0 - push byte 40 - jmp irq_common_stub - -; 41: IRQ9 -irq9: - cli - push byte 0 - push byte 41 - jmp irq_common_stub - -; 42: IRQ10 -irq10: - cli - push byte 0 - push byte 42 - jmp irq_common_stub - -; 43: IRQ11 -irq11: - cli - push byte 0 - push byte 43 - jmp irq_common_stub - -; 44: IRQ12 -irq12: - cli - push byte 0 - push byte 44 - jmp irq_common_stub - -; 45: IRQ13 -irq13: - cli - push byte 0 - push byte 45 - jmp irq_common_stub - -; 46: IRQ14 -irq14: - cli - push byte 0 - push byte 46 - jmp irq_common_stub - -; 47: IRQ15 -irq15: - cli - push byte 0 - push byte 47 - jmp irq_common_stub - -extern irq_handler - -irq_common_stub: - pusha - push ds - push es - push fs - push gs - - mov ax, 0x10 - mov ds, ax - mov es, ax - mov fs, ax - mov gs, ax - mov eax, esp - - push eax - mov eax, irq_handler - call eax - pop eax - - pop gs - pop fs - pop es - pop ds - popa - add esp, 8 - iret diff --git a/src/interrupts/irq.c b/src/interrupts/irq.c deleted file mode 100644 index cf9e1fe..0000000 --- a/src/interrupts/irq.c +++ /dev/null @@ -1,109 +0,0 @@ -#include "../io/io.h" -#include "interrupts.h" -#include "../graphics/graphics.h" - -extern void irq0(); - -extern void irq1(); - -extern void irq2(); - -extern void irq3(); - -extern void irq4(); - -extern void irq5(); - -extern void irq6(); - -extern void irq7(); - -extern void irq8(); - -extern void irq9(); - -extern void irq10(); - -extern void irq11(); - -extern void irq12(); - -extern void irq13(); - -extern void irq14(); - -extern void irq15(); - -// Array to handle custom IRQ handlers -void *irq_routines[16] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 -}; - -// Install custom IRQ handler -void irq_install_handler(int irq, void (*handler)(struct regs *r)) { - irq_routines[irq] = handler; -} - -// Removes the custom IRQ handler -void irq_uninstall_handler(int irq) { - irq_routines[irq] = 0; -} - -int irq_is_installed(int irq) { - return irq_routines[irq] != 0; -} - -// Remap IRQs for protected mode compatibility via the PIC -void irq_remap(void) { - send(0x20, 0x11); - send(0xA0, 0x11); - send(0x21, 0x20); - send(0xA1, 0x28); - send(0x21, 0x04); - send(0xA1, 0x02); - send(0x21, 0x01); - send(0xA1, 0x01); - send(0x21, 0x0); - send(0xA1, 0x0); -} - -// Map ISRs to the correct entries in the IDT -void irq_install() { - irq_remap(); - idt_set_gate(32, (unsigned) irq0, 0x08, 0x8E); - idt_set_gate(33, (unsigned) irq1, 0x08, 0x8E); - idt_set_gate(34, (unsigned) irq2, 0x08, 0x8E); - idt_set_gate(35, (unsigned) irq3, 0x08, 0x8E); - idt_set_gate(36, (unsigned) irq4, 0x08, 0x8E); - idt_set_gate(37, (unsigned) irq5, 0x08, 0x8E); - idt_set_gate(38, (unsigned) irq6, 0x08, 0x8E); - idt_set_gate(39, (unsigned) irq7, 0x08, 0x8E); - idt_set_gate(40, (unsigned) irq8, 0x08, 0x8E); - idt_set_gate(41, (unsigned) irq9, 0x08, 0x8E); - idt_set_gate(42, (unsigned) irq10, 0x08, 0x8E); - idt_set_gate(43, (unsigned) irq11, 0x08, 0x8E); - idt_set_gate(44, (unsigned) irq12, 0x08, 0x8E); - idt_set_gate(45, (unsigned) irq13, 0x08, 0x8E); - idt_set_gate(46, (unsigned) irq14, 0x08, 0x8E); - idt_set_gate(47, (unsigned) irq15, 0x08, 0x8E); -} - -// Handle IRQ ISRs -void irq_handler(struct regs *r) { - void (*handler)(struct regs *r); - - // Execute custom handler if exists - handler = irq_routines[r->int_no - 32]; - if (handler) { - handler(r); - } - - // Send end of interrupt to second (slave) IRQ controller - if (r->int_no >= 40) { - send(0xA0, 0x20); - } - - // Send end of interrupt to master interrupt controller - send(0x20, 0x20); -} diff --git a/src/interrupts/isr.asm b/src/interrupts/isr.asm deleted file mode 100644 index cf75157..0000000 --- a/src/interrupts/isr.asm +++ /dev/null @@ -1,277 +0,0 @@ -global isr0 -global isr1 -global isr2 -global isr3 -global isr4 -global isr5 -global isr6 -global isr7 -global isr8 -global isr9 -global isr10 -global isr11 -global isr12 -global isr13 -global isr14 -global isr15 -global isr16 -global isr17 -global isr18 -global isr19 -global isr20 -global isr21 -global isr22 -global isr23 -global isr24 -global isr25 -global isr26 -global isr27 -global isr28 -global isr29 -global isr30 -global isr31 - -; 0: Divide By Zero Exception -isr0: - cli - push byte 0 - push byte 0 - jmp isr_common_stub - -; 1: Debug Exception -isr1: - cli - push byte 0 - push byte 1 - jmp isr_common_stub - -; 2: Non Maskable Interrupt Exception -isr2: - cli - push byte 0 - push byte 2 - jmp isr_common_stub - -; 3: Int 3 Exception -isr3: - cli - push byte 0 - push byte 3 - jmp isr_common_stub - -; 4: INTO Exception -isr4: - cli - push byte 0 - push byte 4 - jmp isr_common_stub - -; 5: Out of Bounds Exception -isr5: - cli - push byte 0 - push byte 5 - jmp isr_common_stub - -; 6: Invalid Opcode Exception -isr6: - cli - push byte 0 - push byte 6 - jmp isr_common_stub - -; 7: Coprocessor Not Available Exception -isr7: - cli - push byte 0 - push byte 7 - jmp isr_common_stub - -; 8: Double Fault Exception (With Error Code!) -isr8: - cli - push byte 8 - jmp isr_common_stub - -; 9: Coprocessor Segment Overrun Exception -isr9: - cli - push byte 0 - push byte 9 - jmp isr_common_stub - -; 10: Bad TSS Exception (With Error Code!) -isr10: - cli - push byte 10 - jmp isr_common_stub - -; 11: Segment Not Present Exception (With Error Code!) -isr11: - cli - push byte 11 - jmp isr_common_stub - -; 12: Stack Fault Exception (With Error Code!) -isr12: - cli - push byte 12 - jmp isr_common_stub - -; 13: General Protection Fault Exception (With Error Code!) -isr13: - cli - push byte 13 - jmp isr_common_stub - -; 14: Page Fault Exception (With Error Code!) -isr14: - cli - push byte 14 - jmp isr_common_stub - -; 15: Reserved Exception -isr15: - cli - push byte 0 - push byte 15 - jmp isr_common_stub - -; 16: Floating Point Exception -isr16: - cli - push byte 0 - push byte 16 - jmp isr_common_stub - -; 17: Alignment Check Exception -isr17: - cli - push byte 0 - push byte 17 - jmp isr_common_stub - -; 18: Machine Check Exception -isr18: - cli - push byte 0 - push byte 18 - jmp isr_common_stub - -; 19: Reserved -isr19: - cli - push byte 0 - push byte 19 - jmp isr_common_stub - -; 20: Reserved -isr20: - cli - push byte 0 - push byte 20 - jmp isr_common_stub - -; 21: Reserved -isr21: - cli - push byte 0 - push byte 21 - jmp isr_common_stub - -; 22: Reserved -isr22: - cli - push byte 0 - push byte 22 - jmp isr_common_stub - -; 23: Reserved -isr23: - cli - push byte 0 - push byte 23 - jmp isr_common_stub - -; 24: Reserved -isr24: - cli - push byte 0 - push byte 24 - jmp isr_common_stub - -; 25: Reserved -isr25: - cli - push byte 0 - push byte 25 - jmp isr_common_stub - -; 26: Reserved -isr26: - cli - push byte 0 - push byte 26 - jmp isr_common_stub - -; 27: Reserved -isr27: - cli - push byte 0 - push byte 27 - jmp isr_common_stub - -; 28: Reserved -isr28: - cli - push byte 0 - push byte 28 - jmp isr_common_stub - -; 29: Reserved -isr29: - cli - push byte 0 - push byte 29 - jmp isr_common_stub - -; 30: Reserved -isr30: - cli - push byte 0 - push byte 30 - jmp isr_common_stub - -; 31: Reserved -isr31: - cli - push byte 0 - push byte 31 - jmp isr_common_stub - -extern fault_handler - -; Stores the ISR in the stack and calls the C fault handler -isr_common_stub: - pusha - push ds - push es - push fs - push gs - mov ax, 0x10 - mov ds, ax - mov es, ax - mov fs, ax - mov gs, ax - mov eax, esp - push eax - mov eax, fault_handler - call eax - pop eax - pop gs - pop fs - pop es - pop ds - popa - add esp, 8 - iret diff --git a/src/interrupts/isr.c b/src/interrupts/isr.c deleted file mode 100644 index 8da7919..0000000 --- a/src/interrupts/isr.c +++ /dev/null @@ -1,155 +0,0 @@ -#include "../graphics/graphics.h" -#include "interrupts.h" - -// Defined in isr.asm -extern void isr0(); - -extern void isr1(); - -extern void isr2(); - -extern void isr3(); - -extern void isr4(); - -extern void isr5(); - -extern void isr6(); - -extern void isr7(); - -extern void isr8(); - -extern void isr9(); - -extern void isr10(); - -extern void isr11(); - -extern void isr12(); - -extern void isr13(); - -extern void isr14(); - -extern void isr15(); - -extern void isr16(); - -extern void isr17(); - -extern void isr18(); - -extern void isr19(); - -extern void isr20(); - -extern void isr21(); - -extern void isr22(); - -extern void isr23(); - -extern void isr24(); - -extern void isr25(); - -extern void isr26(); - -extern void isr27(); - -extern void isr28(); - -extern void isr29(); - -extern void isr30(); - -extern void isr31(); - -// Install ISRs in IDT -void isrs_install() { - idt_set_gate(0, (unsigned) isr0, 0x08, 0x8E); - idt_set_gate(1, (unsigned) isr1, 0x08, 0x8E); - idt_set_gate(2, (unsigned) isr2, 0x08, 0x8E); - idt_set_gate(3, (unsigned) isr3, 0x08, 0x8E); - idt_set_gate(4, (unsigned) isr4, 0x08, 0x8E); - idt_set_gate(5, (unsigned) isr5, 0x08, 0x8E); - idt_set_gate(6, (unsigned) isr6, 0x08, 0x8E); - idt_set_gate(7, (unsigned) isr7, 0x08, 0x8E); - - idt_set_gate(8, (unsigned) isr8, 0x08, 0x8E); - idt_set_gate(9, (unsigned) isr9, 0x08, 0x8E); - idt_set_gate(10, (unsigned) isr10, 0x08, 0x8E); - idt_set_gate(11, (unsigned) isr11, 0x08, 0x8E); - idt_set_gate(12, (unsigned) isr12, 0x08, 0x8E); - idt_set_gate(13, (unsigned) isr13, 0x08, 0x8E); - idt_set_gate(14, (unsigned) isr14, 0x08, 0x8E); - idt_set_gate(15, (unsigned) isr15, 0x08, 0x8E); - - idt_set_gate(16, (unsigned) isr16, 0x08, 0x8E); - idt_set_gate(17, (unsigned) isr17, 0x08, 0x8E); - idt_set_gate(18, (unsigned) isr18, 0x08, 0x8E); - idt_set_gate(19, (unsigned) isr19, 0x08, 0x8E); - idt_set_gate(20, (unsigned) isr20, 0x08, 0x8E); - idt_set_gate(21, (unsigned) isr21, 0x08, 0x8E); - idt_set_gate(22, (unsigned) isr22, 0x08, 0x8E); - idt_set_gate(23, (unsigned) isr23, 0x08, 0x8E); - - idt_set_gate(24, (unsigned) isr24, 0x08, 0x8E); - idt_set_gate(25, (unsigned) isr25, 0x08, 0x8E); - idt_set_gate(26, (unsigned) isr26, 0x08, 0x8E); - idt_set_gate(27, (unsigned) isr27, 0x08, 0x8E); - idt_set_gate(28, (unsigned) isr28, 0x08, 0x8E); - idt_set_gate(29, (unsigned) isr29, 0x08, 0x8E); - idt_set_gate(30, (unsigned) isr30, 0x08, 0x8E); - idt_set_gate(31, (unsigned) isr31, 0x08, 0x8E); -} - -// Error exception messages -const char *exception_messages[] = { - "Division By Zero", - "Debug", - "Non Maskable Interrupt", - "Breakpoint", - "Into Detected Overflow", - "Out of Bounds", - "Invalid Opcode", - "No Coprocessor", - - "Double Fault", - "Coprocessor Segment Overrun", - "Bad TSS", - "Segment Not Present", - "Stack Fault", - "General Protection Fault", - "Page Fault", - "Unknown Interrupt", - - "Coprocessor Fault", - "Alignment Check", - "Machine Check", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved" -}; - -// Master exception handler - halt via endless loop -void fault_handler(struct regs *r) { - if (r->int_no < 32) { - terminal_write_string("\n"); - terminal_write_string(exception_messages[r->int_no]); - terminal_write_string(" Exception. System Halted!\n"); - for (;;); - } -} diff --git a/src/io/io.asm b/src/io/io.asm deleted file mode 100644 index 6ab3707..0000000 --- a/src/io/io.asm +++ /dev/null @@ -1,10 +0,0 @@ -global shutdown -shutdown: - mov ax, 0x1000 - mov ax, ss - mov sp, 0xf000 - mov ax, 0x5307 - mov bx, 0x0001 - mov cx, 0x0003 - int 0x15 - ret \ No newline at end of file diff --git a/src/io/io.c b/src/io/io.c deleted file mode 100644 index 7bddb13..0000000 --- a/src/io/io.c +++ /dev/null @@ -1,21 +0,0 @@ -#include - -unsigned char receive(unsigned short port) { - unsigned char value; - __asm__ __volatile__ ("inb %1, %0" : "=a" (value) : "dN" (port)); - return value; -} - -void send(unsigned short port, unsigned char data) { - __asm__ __volatile__ ("outb %1, %0" : : "dN" (port), "a" (data)); -} - -void reboot() { - uint8_t good = 0x02; - while (good & 0x02) - good = receive(0x64); - send(0x64, 0xFE); - loop: - asm volatile ("hlt"); - goto loop; -} \ No newline at end of file diff --git a/src/io/io.h b/src/io/io.h deleted file mode 100644 index e00a5f0..0000000 --- a/src/io/io.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef MELVIX_IO_H -#define MELVIX_IO_H - -#include - -unsigned char receive(unsigned short port); - -void send(unsigned short port, unsigned char data); - -void reboot(); - -#endif diff --git a/src/kernel.c b/src/kernel.c deleted file mode 100644 index e08c370..0000000 --- a/src/kernel.c +++ /dev/null @@ -1,32 +0,0 @@ -#include "graphics/graphics.h" -#include "gdt/gdt.h" -#include "interrupts/interrupts.h" -#include "input/input.h" -#include "timer/timer.h" -#include "sound/sound.h" - -void kernel_main(void) { - gdt_install(); - idt_install(); - isrs_install(); - irq_install(); - - __asm__ __volatile__ ("sti"); - - terminal_initialize(); - terminal_write_string("Melvix loaded successfully!\n"); - - timer_install(); - keyboard_install(); - mouse_install(); - - beep(262, 20); - beep(294, 20); - beep(330, 20); - beep(349, 20); - beep(392, 20); - beep(440, 20); - beep(494, 20); - beep(523, 20); - // __asm__ ("div %0" :: "r"(0)); // Exception testing x/0 -} \ No newline at end of file diff --git a/src/kernel/boot.asm b/src/kernel/boot.asm new file mode 100644 index 0000000..eddd3a4 --- /dev/null +++ b/src/kernel/boot.asm @@ -0,0 +1,50 @@ +[BITS 32] +global start +start: + mov esp, _sys_stack ; Points stack to stack area + jmp stublet + +; Align with 4 Bytes +ALIGN 4 +mboot: + ; Multiboot macros + MULTIBOOT_PAGE_ALIGN equ 1<<0 + MULTIBOOT_MEMORY_INFO equ 1<<1 + MULTIBOOT_AOUT_KLUDGE equ 1<<16 + MULTIBOOT_HEADER_MAGIC equ 0x1BADB002 + MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO | MULTIBOOT_AOUT_KLUDGE + MULTIBOOT_CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) + EXTERN code, bss, end + + ; GRUB Multiboot header + dd MULTIBOOT_HEADER_MAGIC + dd MULTIBOOT_HEADER_FLAGS + dd MULTIBOOT_CHECKSUM + + ; AOUT kludge + dd mboot + dd code + dd bss + dd end + dd start + +; Endless loop +stublet: + extern kernel_main + call kernel_main + jmp $ + +%include "src/kernel/gdt/gdt.asm" + +%include "src/kernel/interrupts/idt.asm" + +%include "src/kernel/interrupts/isr.asm" + +%include "src/kernel/interrupts/irq.asm" + +%include "src/kernel/io/io.asm" + +; Store the stack +SECTION .bss + resb 8192 ; Reserve 8KiB +_sys_stack: \ No newline at end of file diff --git a/src/kernel/commands/command.c b/src/kernel/commands/command.c new file mode 100644 index 0000000..9cbcb07 --- /dev/null +++ b/src/kernel/commands/command.c @@ -0,0 +1,26 @@ +#include "../graphics/graphics.h" +#include "../lib/lib.h" +#include "../io/io.h" + +int32_t starts_with(const char *a, const char *b) { + size_t length_pre = strlen(b); + size_t length_main = strlen(a); + return length_main < length_pre ? 0 : memory_compare(b, a, length_pre) == 0; +} + +extern void shutdown(); + +void exec_command(char *command) { + if (starts_with(command, "ls")) + terminal_write_line("Listing files"); + else if (starts_with(command, "help")) + terminal_write_line("I can't help you write now"); + else if (starts_with(command, "ping")) + terminal_write_line("pong!"); + else if (starts_with(command, "shutdown")) + shutdown(); + else if (starts_with(command, "reboot")) + reboot(); + else + terminal_write_line("Command not found!"); +} diff --git a/src/kernel/commands/command.h b/src/kernel/commands/command.h new file mode 100644 index 0000000..2a43416 --- /dev/null +++ b/src/kernel/commands/command.h @@ -0,0 +1,6 @@ +#ifndef MELVIX_COMMAND_H +#define MELVIX_COMMAND_H + +void exec_command(char *command); + +#endif diff --git a/src/kernel/gdt/gdt.asm b/src/kernel/gdt/gdt.asm new file mode 100644 index 0000000..c2128e4 --- /dev/null +++ b/src/kernel/gdt/gdt.asm @@ -0,0 +1,14 @@ +; GDT flush function +global gdt_flush +extern gp +gdt_flush: + lgdt [gp] + mov ax, 0x10 ; Data segment offset of GDT + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + jmp 0x08:flush2 ; Code segment offset +flush2: + ret ; Returns to C code \ No newline at end of file diff --git a/src/kernel/gdt/gdt.c b/src/kernel/gdt/gdt.c new file mode 100644 index 0000000..813b432 --- /dev/null +++ b/src/kernel/gdt/gdt.c @@ -0,0 +1,51 @@ +struct gdt_entry { + unsigned short limit_low; + unsigned short base_low; + unsigned char base_middle; + unsigned char access; + unsigned char granularity; + unsigned char base_high; +} __attribute__((packed)); + +struct gdt_ptr { + unsigned short limit; + unsigned int base; +} __attribute__((packed)); + +struct gdt_entry gdt[3]; +struct gdt_ptr gp; + +extern void gdt_flush(); + +void gdt_set_gate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran) { + // Set descriptor base address + gdt[num].base_low = (base & 0xFFFF); + gdt[num].base_middle = (base >> 16) & 0xFF; + gdt[num].base_high = (base >> 24) & 0xFF; + + // Set descriptor limits + gdt[num].limit_low = (limit & 0xFFFF); + gdt[num].granularity = ((limit >> 16) & 0x0F); + + // Set granularity and access flags + gdt[num].granularity |= (gran & 0xF0); + gdt[num].access = access; +} + +void gdt_install() { + // Set GDT pointer and limit + gp.limit = (sizeof(struct gdt_entry) * 3) - 1; + gp.base = &gdt; + + // NULL descriptor + gdt_set_gate(0, 0, 0, 0, 0); + + // Code segment + gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); + + // Data segment + gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); + + // Remove old GDT and install the new changes! + gdt_flush(); +} \ No newline at end of file diff --git a/src/kernel/gdt/gdt.h b/src/kernel/gdt/gdt.h new file mode 100644 index 0000000..46d80e2 --- /dev/null +++ b/src/kernel/gdt/gdt.h @@ -0,0 +1,6 @@ +#ifndef MELVIX_GDT_H +#define MELVIX_GDT_H + +void gdt_install(); + +#endif diff --git a/src/kernel/graphics/graphics.h b/src/kernel/graphics/graphics.h new file mode 100644 index 0000000..a9ed917 --- /dev/null +++ b/src/kernel/graphics/graphics.h @@ -0,0 +1,21 @@ +#ifndef MELVIX_VGA_H +#define MELVIX_VGA_H + +#include +#include + +enum vga_color; + +void terminal_initialize(void); + +void terminal_set_color(uint8_t color); + +void terminal_clear(); + +void terminal_write_string(const char *data); + +void terminal_put_char(char c); + +void terminal_write_line(const char *data); + +#endif \ No newline at end of file diff --git a/src/kernel/graphics/vga.c b/src/kernel/graphics/vga.c new file mode 100644 index 0000000..86c00ff --- /dev/null +++ b/src/kernel/graphics/vga.c @@ -0,0 +1,145 @@ +#include +#include +#include "../io/io.h" +#include "../lib/lib.h" +#include "../commands/command.h" +#include "../interrupts/interrupts.h" + +// Hardware text mode color constants +enum vga_color { + VGA_COLOR_BLACK = 0, + VGA_COLOR_BLUE = 1, + VGA_COLOR_GREEN = 2, + VGA_COLOR_CYAN = 3, + VGA_COLOR_RED = 4, + VGA_COLOR_MAGENTA = 5, + VGA_COLOR_BROWN = 6, + VGA_COLOR_LIGHT_GREY = 7, + VGA_COLOR_DARK_GREY = 8, + VGA_COLOR_LIGHT_BLUE = 9, + VGA_COLOR_LIGHT_GREEN = 10, + VGA_COLOR_LIGHT_CYAN = 11, + VGA_COLOR_LIGHT_RED = 12, + VGA_COLOR_LIGHT_MAGENTA = 13, + VGA_COLOR_LIGHT_BROWN = 14, + VGA_COLOR_WHITE = 15, +}; + +static inline uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg) { + return fg | bg << 4; +} + +static inline uint16_t vga_entry(unsigned char uc, uint8_t color) { + return (uint16_t) uc | (uint16_t) color << 8; +} + +static const size_t VGA_WIDTH = 80; +static const size_t VGA_HEIGHT = 25; + +size_t terminal_row; +size_t terminal_column; +uint8_t terminal_color; +uint16_t *terminal_buffer; + +char text[1024] = {0}; + +void terminal_clear() { + for (size_t y = 0; y < VGA_HEIGHT; y++) { + for (size_t x = 0; x < VGA_WIDTH; x++) { + const size_t index = y * VGA_WIDTH + x; + terminal_buffer[index] = vga_entry(' ', terminal_color); + } + } +} + +void terminal_enable_cursor(uint8_t cursor_start, uint8_t cursor_end) { + send(0x3D4, 0x0A); + send(0x3D5, (receive(0x3D5) & 0xC0) | cursor_start); + send(0x3D4, 0x0B); + send(0x3D5, (receive(0x3D5) & 0xE0) | cursor_end); +} + +void terminal_update_cursor(void) { + unsigned temp = terminal_row * VGA_WIDTH + terminal_column; + send(0x3D4, 14); + send(0x3D5, temp >> 8); + send(0x3D4, 15); + send(0x3D5, temp); +} + +void terminal_initialize(void) { + terminal_enable_cursor(0, 15); + terminal_row = 0; + terminal_column = 0; + terminal_color = vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK); + terminal_buffer = (uint16_t *) 0xB8000; + terminal_clear(); +} + +void terminal_scroll(void) { + if (terminal_row >= VGA_HEIGHT) { + terminal_row = VGA_HEIGHT - 1; + for (size_t x = 0; x < VGA_WIDTH; x++) + for (size_t y = 0; y < VGA_HEIGHT; y++) { + uint16_t c = terminal_buffer[y * VGA_WIDTH + x]; + terminal_buffer[(y - 1) * VGA_WIDTH + x] = c; + terminal_buffer[y * VGA_WIDTH + x] = vga_entry(' ', terminal_color); + } + } +} + +void terminal_set_color(uint8_t color) { + terminal_color = color; +} + +void terminal_put_entry_at(char c, uint8_t color, size_t x, size_t y) { + const size_t index = y * VGA_WIDTH + x; + terminal_buffer[index] = vga_entry(c, color); +} + +void terminal_put_char(char c) { + if (c == 0x08) { + if (terminal_column != 0) terminal_column--; + } else if (c == 0x09) { + terminal_column = (terminal_column + 8) & ~(8 - 1); + } else if (c == '\r') { + terminal_column = 0; + } else if (c == '\n') { + if (irq_is_installed(1)) exec_command(text); + memory_set(text, 0, sizeof(text)); + terminal_column = 0; + terminal_row++; + terminal_scroll(); + terminal_put_entry_at('$', terminal_color, terminal_column, terminal_row); + terminal_column = 2; + } else if (c >= ' ') { // Any printable character + strcat(text, &c); + terminal_put_entry_at(c, terminal_color, terminal_column, terminal_row); + terminal_column++; + } + + // Add new line on overflow + if (terminal_column >= VGA_WIDTH) { + terminal_column = 0; + terminal_row++; + } + + terminal_scroll(); + terminal_update_cursor(); +} + +void terminal_write(const char *data, size_t size) { + for (size_t i = 0; i < size; i++) + terminal_put_char(data[i]); +} + +void terminal_write_string(const char *data) { + terminal_write(data, strlen(data)); +} + +void terminal_write_line(const char *data) { + terminal_row++; + terminal_column = 0; + terminal_write_string(data); + terminal_column = 0; +} diff --git a/src/kernel/grub.cfg b/src/kernel/grub.cfg new file mode 100644 index 0000000..1029549 --- /dev/null +++ b/src/kernel/grub.cfg @@ -0,0 +1,6 @@ +set timeout = 0 +set default = 0 + +menuentry "Melvix" { +multiboot /boot/melvix.bin +} \ No newline at end of file diff --git a/src/kernel/input/input.h b/src/kernel/input/input.h new file mode 100644 index 0000000..60d2f79 --- /dev/null +++ b/src/kernel/input/input.h @@ -0,0 +1,10 @@ +#ifndef MELVIX_INPUT_H +#define MELVIX_INPUT_H + +void mouse_install(); + +char get_mouse(int n); + +void keyboard_install(); + +#endif diff --git a/src/kernel/input/ps2/keyboard.c b/src/kernel/input/ps2/keyboard.c new file mode 100644 index 0000000..ae17675 --- /dev/null +++ b/src/kernel/input/ps2/keyboard.c @@ -0,0 +1,50 @@ +#include "../../interrupts/interrupts.h" +#include "../../io/io.h" +#include "../../graphics/graphics.h" + +unsigned char keymap[128] = { + 0 /*E*/, 27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', + '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', + 0 /*C*/, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0 /*LS*/, + '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0 /*RS*/, '*', + 0, // Alt key + ' ', // Space bar + 0, // Caps lock + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // F keys + 0, // Num lock + 0, // Scroll lock + 0, // Home key + 0, // Up arrow + 0, // Page up + '-', + 0, // Left arrow + 0, + 0, // Right arrow + '+', + 0, // End key + 0, // Down arrow + 0, // Page down + 0, // Insert key + 0, // Delete key + 0, 0, 0, + 0, // F11 + 0, // F12 + 0, // Other keys +}; + +void keyboard_handler(struct regs *r) { + unsigned char scan_code; + + scan_code = receive(0x60); + + if (scan_code & 0x80) { + // Release + } else { + terminal_put_char(keymap[scan_code]); + } +} + +/* Installs the keyboard handler into IRQ1 */ +void keyboard_install() { + irq_install_handler(1, keyboard_handler); +} diff --git a/src/kernel/input/ps2/mouse.c b/src/kernel/input/ps2/mouse.c new file mode 100644 index 0000000..49c5a6c --- /dev/null +++ b/src/kernel/input/ps2/mouse.c @@ -0,0 +1,107 @@ +#include "../../io/io.h" +#include "../../interrupts/interrupts.h" + +char mouse_cycle = 0; +signed char mouse_byte[3], mouse_ex[3]; +signed char mouse_x = 0; +signed char mouse_y = 0; +int mouse_but_1 = 0; +int mouse_but_2 = 0; +int mm_n[3] = {0, 0, 0,}; + +void mouse_handler(struct regs *a_r) { + switch (mouse_cycle) { + case 0: + mouse_byte[0] = receive(0x60); + mouse_cycle++; + break; + case 1: + mouse_byte[1] = receive(0x60); + mouse_cycle++; + break; + case 2: + mouse_byte[2] = receive(0x60); + mouse_x = mouse_byte[1]; + mouse_y = mouse_byte[2]; + mouse_but_1 = (mouse_byte[0] % 2); + mouse_but_2 = ((mouse_byte[0] % 4) - (mouse_byte[0] % 2)) / 2; + mouse_cycle = 0; + mouse_ex[0] = mouse_byte[0]; + mm_n[0] = 1; + mouse_ex[1] = mouse_byte[1]; + mm_n[1] = 1; + mouse_ex[2] = mouse_byte[2]; + mm_n[2] = 1; + break; + default: + break; + } +} + +inline void mouse_wait(char a_type) { + unsigned int _time_out = 100000; + if (a_type == 0) { + while (_time_out--) { + if ((receive(0x64) & 1) == 1) { + return; + } + } + return; + } else { + while (_time_out--) { + if ((receive(0x64) & 2) == 0) { + return; + } + } + return; + } +} + +inline void mouse_write(char a_write) { + mouse_wait(1); + send(0x64, 0xD4); + mouse_wait(1); + send(0x60, a_write); +} + +char mouse_read() { + mouse_wait(0); + return receive(0x60); +} + +void mouse_install() { + char _status; + + // Enable auxiliary mouse device + mouse_wait(1); + send(0x64, 0xA8); + + // Enable interrupts + mouse_wait(1); + send(0x64, 0x20); + mouse_wait(0); + _status = (receive(0x60) | 2); + mouse_wait(1); + send(0x64, 0x60); + mouse_wait(1); + send(0x60, _status); + + // Use default settings + mouse_write(0xF6); + mouse_read(); + + // Enable mouse + mouse_write(0xF4); + mouse_read(); + + // Setup the mouse handler + irq_install_handler(2, mouse_handler); +} + +char get_mouse(int n) { + if (mm_n[n] == 1) { + mm_n[n] = 0; + return mouse_ex[n]; + } else + return 0; +} \ No newline at end of file diff --git a/src/kernel/interrupts/idt.asm b/src/kernel/interrupts/idt.asm new file mode 100644 index 0000000..90eab47 --- /dev/null +++ b/src/kernel/interrupts/idt.asm @@ -0,0 +1,6 @@ +; IDT loader +global idt_load +extern idtp +idt_load: + lidt [idtp] + ret diff --git a/src/kernel/interrupts/idt.c b/src/kernel/interrupts/idt.c new file mode 100644 index 0000000..ba71339 --- /dev/null +++ b/src/kernel/interrupts/idt.c @@ -0,0 +1,46 @@ +#include "../lib/lib.h" + +struct idt_entry { + unsigned short base_lo; + unsigned short sel; // Kernel segment + unsigned char always0; // Always 0 + unsigned char flags; + unsigned short base_hi; +} __attribute__((packed)); + +struct idt_ptr { + unsigned short limit; + unsigned int base; +} __attribute__((packed)); + +// Initialize IDT with 256 entries +struct idt_entry idt[256]; +struct idt_ptr idtp; + +// Defined in idt.asm +extern void idt_load(); + +void idt_set_gate(unsigned char num, unsigned long base, unsigned short sel, unsigned char flags) { + // Specify the interrupt routine's base address + idt[num].base_lo = (base & 0xFFFF); + idt[num].base_hi = (base >> 16) & 0xFFFF; + + // Set selector/segment of IDT entry + idt[num].sel = sel; + idt[num].always0 = 0; + idt[num].flags = flags; +} + +// Install IDT +void idt_install() { + // Set IDT pointer and limit + idtp.limit = (sizeof(struct idt_entry) * 256) - 1; + idtp.base = &idt; + + // Clear IDT by setting memory cells to 0 + memory_set(&idt, 0, sizeof(struct idt_entry) * 256); + + // TODO: Add method to add ISRs to IDT + + idt_load(); +} diff --git a/src/kernel/interrupts/interrupts.h b/src/kernel/interrupts/interrupts.h new file mode 100644 index 0000000..755a633 --- /dev/null +++ b/src/kernel/interrupts/interrupts.h @@ -0,0 +1,30 @@ +#ifndef MELVIX_INTERRUPTS_H +#define MELVIX_INTERRUPTS_H + +// IDT +void idt_install(); + +void idt_set_gate(unsigned char num, unsigned long base, unsigned short sel, unsigned char flags); + +// ISRS +void isrs_install(); + +struct regs { + unsigned int gs, fs, es, ds; + unsigned int edi, esi, ebp, esp, ebx, edx, ecx, eax; + unsigned int int_no, err_code; + unsigned int eip, cs, eflags, useresp, ss; +}; + +// IRQ +void irq_install(); + +void irq_install_handler(int irq, void (*handler)(struct regs *r)); + +void irq_uninstall_handler(int irq); + +void irq_handler(struct regs *r); + +int irq_is_installed(int irq); + +#endif diff --git a/src/kernel/interrupts/irq.asm b/src/kernel/interrupts/irq.asm new file mode 100644 index 0000000..c485613 --- /dev/null +++ b/src/kernel/interrupts/irq.asm @@ -0,0 +1,157 @@ +global irq0 +global irq1 +global irq2 +global irq3 +global irq4 +global irq5 +global irq6 +global irq7 +global irq8 +global irq9 +global irq10 +global irq11 +global irq12 +global irq13 +global irq14 +global irq15 + +; 32: IRQ0 +irq0: + cli + push byte 0 + push byte 32 + jmp irq_common_stub + +; 33: IRQ1 +irq1: + cli + push byte 0 + push byte 33 + jmp irq_common_stub + +; 34: IRQ2 +irq2: + cli + push byte 0 + push byte 34 + jmp irq_common_stub + +; 35: IRQ3 +irq3: + cli + push byte 0 + push byte 35 + jmp irq_common_stub + +; 36: IRQ4 +irq4: + cli + push byte 0 + push byte 36 + jmp irq_common_stub + +; 37: IRQ5 +irq5: + cli + push byte 0 + push byte 37 + jmp irq_common_stub + +; 38: IRQ6 +irq6: + cli + push byte 0 + push byte 38 + jmp irq_common_stub + +; 39: IRQ7 +irq7: + cli + push byte 0 + push byte 39 + jmp irq_common_stub + +; 40: IRQ8 +irq8: + cli + push byte 0 + push byte 40 + jmp irq_common_stub + +; 41: IRQ9 +irq9: + cli + push byte 0 + push byte 41 + jmp irq_common_stub + +; 42: IRQ10 +irq10: + cli + push byte 0 + push byte 42 + jmp irq_common_stub + +; 43: IRQ11 +irq11: + cli + push byte 0 + push byte 43 + jmp irq_common_stub + +; 44: IRQ12 +irq12: + cli + push byte 0 + push byte 44 + jmp irq_common_stub + +; 45: IRQ13 +irq13: + cli + push byte 0 + push byte 45 + jmp irq_common_stub + +; 46: IRQ14 +irq14: + cli + push byte 0 + push byte 46 + jmp irq_common_stub + +; 47: IRQ15 +irq15: + cli + push byte 0 + push byte 47 + jmp irq_common_stub + +extern irq_handler + +irq_common_stub: + pusha + push ds + push es + push fs + push gs + + mov ax, 0x10 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov eax, esp + + push eax + mov eax, irq_handler + call eax + pop eax + + pop gs + pop fs + pop es + pop ds + popa + add esp, 8 + iret diff --git a/src/kernel/interrupts/irq.c b/src/kernel/interrupts/irq.c new file mode 100644 index 0000000..cf9e1fe --- /dev/null +++ b/src/kernel/interrupts/irq.c @@ -0,0 +1,109 @@ +#include "../io/io.h" +#include "interrupts.h" +#include "../graphics/graphics.h" + +extern void irq0(); + +extern void irq1(); + +extern void irq2(); + +extern void irq3(); + +extern void irq4(); + +extern void irq5(); + +extern void irq6(); + +extern void irq7(); + +extern void irq8(); + +extern void irq9(); + +extern void irq10(); + +extern void irq11(); + +extern void irq12(); + +extern void irq13(); + +extern void irq14(); + +extern void irq15(); + +// Array to handle custom IRQ handlers +void *irq_routines[16] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +// Install custom IRQ handler +void irq_install_handler(int irq, void (*handler)(struct regs *r)) { + irq_routines[irq] = handler; +} + +// Removes the custom IRQ handler +void irq_uninstall_handler(int irq) { + irq_routines[irq] = 0; +} + +int irq_is_installed(int irq) { + return irq_routines[irq] != 0; +} + +// Remap IRQs for protected mode compatibility via the PIC +void irq_remap(void) { + send(0x20, 0x11); + send(0xA0, 0x11); + send(0x21, 0x20); + send(0xA1, 0x28); + send(0x21, 0x04); + send(0xA1, 0x02); + send(0x21, 0x01); + send(0xA1, 0x01); + send(0x21, 0x0); + send(0xA1, 0x0); +} + +// Map ISRs to the correct entries in the IDT +void irq_install() { + irq_remap(); + idt_set_gate(32, (unsigned) irq0, 0x08, 0x8E); + idt_set_gate(33, (unsigned) irq1, 0x08, 0x8E); + idt_set_gate(34, (unsigned) irq2, 0x08, 0x8E); + idt_set_gate(35, (unsigned) irq3, 0x08, 0x8E); + idt_set_gate(36, (unsigned) irq4, 0x08, 0x8E); + idt_set_gate(37, (unsigned) irq5, 0x08, 0x8E); + idt_set_gate(38, (unsigned) irq6, 0x08, 0x8E); + idt_set_gate(39, (unsigned) irq7, 0x08, 0x8E); + idt_set_gate(40, (unsigned) irq8, 0x08, 0x8E); + idt_set_gate(41, (unsigned) irq9, 0x08, 0x8E); + idt_set_gate(42, (unsigned) irq10, 0x08, 0x8E); + idt_set_gate(43, (unsigned) irq11, 0x08, 0x8E); + idt_set_gate(44, (unsigned) irq12, 0x08, 0x8E); + idt_set_gate(45, (unsigned) irq13, 0x08, 0x8E); + idt_set_gate(46, (unsigned) irq14, 0x08, 0x8E); + idt_set_gate(47, (unsigned) irq15, 0x08, 0x8E); +} + +// Handle IRQ ISRs +void irq_handler(struct regs *r) { + void (*handler)(struct regs *r); + + // Execute custom handler if exists + handler = irq_routines[r->int_no - 32]; + if (handler) { + handler(r); + } + + // Send end of interrupt to second (slave) IRQ controller + if (r->int_no >= 40) { + send(0xA0, 0x20); + } + + // Send end of interrupt to master interrupt controller + send(0x20, 0x20); +} diff --git a/src/kernel/interrupts/isr.asm b/src/kernel/interrupts/isr.asm new file mode 100644 index 0000000..cf75157 --- /dev/null +++ b/src/kernel/interrupts/isr.asm @@ -0,0 +1,277 @@ +global isr0 +global isr1 +global isr2 +global isr3 +global isr4 +global isr5 +global isr6 +global isr7 +global isr8 +global isr9 +global isr10 +global isr11 +global isr12 +global isr13 +global isr14 +global isr15 +global isr16 +global isr17 +global isr18 +global isr19 +global isr20 +global isr21 +global isr22 +global isr23 +global isr24 +global isr25 +global isr26 +global isr27 +global isr28 +global isr29 +global isr30 +global isr31 + +; 0: Divide By Zero Exception +isr0: + cli + push byte 0 + push byte 0 + jmp isr_common_stub + +; 1: Debug Exception +isr1: + cli + push byte 0 + push byte 1 + jmp isr_common_stub + +; 2: Non Maskable Interrupt Exception +isr2: + cli + push byte 0 + push byte 2 + jmp isr_common_stub + +; 3: Int 3 Exception +isr3: + cli + push byte 0 + push byte 3 + jmp isr_common_stub + +; 4: INTO Exception +isr4: + cli + push byte 0 + push byte 4 + jmp isr_common_stub + +; 5: Out of Bounds Exception +isr5: + cli + push byte 0 + push byte 5 + jmp isr_common_stub + +; 6: Invalid Opcode Exception +isr6: + cli + push byte 0 + push byte 6 + jmp isr_common_stub + +; 7: Coprocessor Not Available Exception +isr7: + cli + push byte 0 + push byte 7 + jmp isr_common_stub + +; 8: Double Fault Exception (With Error Code!) +isr8: + cli + push byte 8 + jmp isr_common_stub + +; 9: Coprocessor Segment Overrun Exception +isr9: + cli + push byte 0 + push byte 9 + jmp isr_common_stub + +; 10: Bad TSS Exception (With Error Code!) +isr10: + cli + push byte 10 + jmp isr_common_stub + +; 11: Segment Not Present Exception (With Error Code!) +isr11: + cli + push byte 11 + jmp isr_common_stub + +; 12: Stack Fault Exception (With Error Code!) +isr12: + cli + push byte 12 + jmp isr_common_stub + +; 13: General Protection Fault Exception (With Error Code!) +isr13: + cli + push byte 13 + jmp isr_common_stub + +; 14: Page Fault Exception (With Error Code!) +isr14: + cli + push byte 14 + jmp isr_common_stub + +; 15: Reserved Exception +isr15: + cli + push byte 0 + push byte 15 + jmp isr_common_stub + +; 16: Floating Point Exception +isr16: + cli + push byte 0 + push byte 16 + jmp isr_common_stub + +; 17: Alignment Check Exception +isr17: + cli + push byte 0 + push byte 17 + jmp isr_common_stub + +; 18: Machine Check Exception +isr18: + cli + push byte 0 + push byte 18 + jmp isr_common_stub + +; 19: Reserved +isr19: + cli + push byte 0 + push byte 19 + jmp isr_common_stub + +; 20: Reserved +isr20: + cli + push byte 0 + push byte 20 + jmp isr_common_stub + +; 21: Reserved +isr21: + cli + push byte 0 + push byte 21 + jmp isr_common_stub + +; 22: Reserved +isr22: + cli + push byte 0 + push byte 22 + jmp isr_common_stub + +; 23: Reserved +isr23: + cli + push byte 0 + push byte 23 + jmp isr_common_stub + +; 24: Reserved +isr24: + cli + push byte 0 + push byte 24 + jmp isr_common_stub + +; 25: Reserved +isr25: + cli + push byte 0 + push byte 25 + jmp isr_common_stub + +; 26: Reserved +isr26: + cli + push byte 0 + push byte 26 + jmp isr_common_stub + +; 27: Reserved +isr27: + cli + push byte 0 + push byte 27 + jmp isr_common_stub + +; 28: Reserved +isr28: + cli + push byte 0 + push byte 28 + jmp isr_common_stub + +; 29: Reserved +isr29: + cli + push byte 0 + push byte 29 + jmp isr_common_stub + +; 30: Reserved +isr30: + cli + push byte 0 + push byte 30 + jmp isr_common_stub + +; 31: Reserved +isr31: + cli + push byte 0 + push byte 31 + jmp isr_common_stub + +extern fault_handler + +; Stores the ISR in the stack and calls the C fault handler +isr_common_stub: + pusha + push ds + push es + push fs + push gs + mov ax, 0x10 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov eax, esp + push eax + mov eax, fault_handler + call eax + pop eax + pop gs + pop fs + pop es + pop ds + popa + add esp, 8 + iret diff --git a/src/kernel/interrupts/isr.c b/src/kernel/interrupts/isr.c new file mode 100644 index 0000000..8da7919 --- /dev/null +++ b/src/kernel/interrupts/isr.c @@ -0,0 +1,155 @@ +#include "../graphics/graphics.h" +#include "interrupts.h" + +// Defined in isr.asm +extern void isr0(); + +extern void isr1(); + +extern void isr2(); + +extern void isr3(); + +extern void isr4(); + +extern void isr5(); + +extern void isr6(); + +extern void isr7(); + +extern void isr8(); + +extern void isr9(); + +extern void isr10(); + +extern void isr11(); + +extern void isr12(); + +extern void isr13(); + +extern void isr14(); + +extern void isr15(); + +extern void isr16(); + +extern void isr17(); + +extern void isr18(); + +extern void isr19(); + +extern void isr20(); + +extern void isr21(); + +extern void isr22(); + +extern void isr23(); + +extern void isr24(); + +extern void isr25(); + +extern void isr26(); + +extern void isr27(); + +extern void isr28(); + +extern void isr29(); + +extern void isr30(); + +extern void isr31(); + +// Install ISRs in IDT +void isrs_install() { + idt_set_gate(0, (unsigned) isr0, 0x08, 0x8E); + idt_set_gate(1, (unsigned) isr1, 0x08, 0x8E); + idt_set_gate(2, (unsigned) isr2, 0x08, 0x8E); + idt_set_gate(3, (unsigned) isr3, 0x08, 0x8E); + idt_set_gate(4, (unsigned) isr4, 0x08, 0x8E); + idt_set_gate(5, (unsigned) isr5, 0x08, 0x8E); + idt_set_gate(6, (unsigned) isr6, 0x08, 0x8E); + idt_set_gate(7, (unsigned) isr7, 0x08, 0x8E); + + idt_set_gate(8, (unsigned) isr8, 0x08, 0x8E); + idt_set_gate(9, (unsigned) isr9, 0x08, 0x8E); + idt_set_gate(10, (unsigned) isr10, 0x08, 0x8E); + idt_set_gate(11, (unsigned) isr11, 0x08, 0x8E); + idt_set_gate(12, (unsigned) isr12, 0x08, 0x8E); + idt_set_gate(13, (unsigned) isr13, 0x08, 0x8E); + idt_set_gate(14, (unsigned) isr14, 0x08, 0x8E); + idt_set_gate(15, (unsigned) isr15, 0x08, 0x8E); + + idt_set_gate(16, (unsigned) isr16, 0x08, 0x8E); + idt_set_gate(17, (unsigned) isr17, 0x08, 0x8E); + idt_set_gate(18, (unsigned) isr18, 0x08, 0x8E); + idt_set_gate(19, (unsigned) isr19, 0x08, 0x8E); + idt_set_gate(20, (unsigned) isr20, 0x08, 0x8E); + idt_set_gate(21, (unsigned) isr21, 0x08, 0x8E); + idt_set_gate(22, (unsigned) isr22, 0x08, 0x8E); + idt_set_gate(23, (unsigned) isr23, 0x08, 0x8E); + + idt_set_gate(24, (unsigned) isr24, 0x08, 0x8E); + idt_set_gate(25, (unsigned) isr25, 0x08, 0x8E); + idt_set_gate(26, (unsigned) isr26, 0x08, 0x8E); + idt_set_gate(27, (unsigned) isr27, 0x08, 0x8E); + idt_set_gate(28, (unsigned) isr28, 0x08, 0x8E); + idt_set_gate(29, (unsigned) isr29, 0x08, 0x8E); + idt_set_gate(30, (unsigned) isr30, 0x08, 0x8E); + idt_set_gate(31, (unsigned) isr31, 0x08, 0x8E); +} + +// Error exception messages +const char *exception_messages[] = { + "Division By Zero", + "Debug", + "Non Maskable Interrupt", + "Breakpoint", + "Into Detected Overflow", + "Out of Bounds", + "Invalid Opcode", + "No Coprocessor", + + "Double Fault", + "Coprocessor Segment Overrun", + "Bad TSS", + "Segment Not Present", + "Stack Fault", + "General Protection Fault", + "Page Fault", + "Unknown Interrupt", + + "Coprocessor Fault", + "Alignment Check", + "Machine Check", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved" +}; + +// Master exception handler - halt via endless loop +void fault_handler(struct regs *r) { + if (r->int_no < 32) { + terminal_write_string("\n"); + terminal_write_string(exception_messages[r->int_no]); + terminal_write_string(" Exception. System Halted!\n"); + for (;;); + } +} diff --git a/src/kernel/io/io.asm b/src/kernel/io/io.asm new file mode 100644 index 0000000..6ab3707 --- /dev/null +++ b/src/kernel/io/io.asm @@ -0,0 +1,10 @@ +global shutdown +shutdown: + mov ax, 0x1000 + mov ax, ss + mov sp, 0xf000 + mov ax, 0x5307 + mov bx, 0x0001 + mov cx, 0x0003 + int 0x15 + ret \ No newline at end of file diff --git a/src/kernel/io/io.c b/src/kernel/io/io.c new file mode 100644 index 0000000..7bddb13 --- /dev/null +++ b/src/kernel/io/io.c @@ -0,0 +1,21 @@ +#include + +unsigned char receive(unsigned short port) { + unsigned char value; + __asm__ __volatile__ ("inb %1, %0" : "=a" (value) : "dN" (port)); + return value; +} + +void send(unsigned short port, unsigned char data) { + __asm__ __volatile__ ("outb %1, %0" : : "dN" (port), "a" (data)); +} + +void reboot() { + uint8_t good = 0x02; + while (good & 0x02) + good = receive(0x64); + send(0x64, 0xFE); + loop: + asm volatile ("hlt"); + goto loop; +} \ No newline at end of file diff --git a/src/kernel/io/io.h b/src/kernel/io/io.h new file mode 100644 index 0000000..e00a5f0 --- /dev/null +++ b/src/kernel/io/io.h @@ -0,0 +1,12 @@ +#ifndef MELVIX_IO_H +#define MELVIX_IO_H + +#include + +unsigned char receive(unsigned short port); + +void send(unsigned short port, unsigned char data); + +void reboot(); + +#endif diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c new file mode 100644 index 0000000..49fe0b7 --- /dev/null +++ b/src/kernel/kernel.c @@ -0,0 +1,23 @@ +#include "graphics/graphics.h" +#include "gdt/gdt.h" +#include "interrupts/interrupts.h" +#include "input/input.h" +#include "timer/timer.h" +#include "sound/sound.h" + +void kernel_main(void) { + gdt_install(); + idt_install(); + isrs_install(); + irq_install(); + + __asm__ __volatile__ ("sti"); + + terminal_initialize(); + terminal_write_string("Melvix loaded successfully!\n"); + + timer_install(); + keyboard_install(); + mouse_install(); + // __asm__ ("div %0" :: "r"(0)); // Exception testing x/0 +} \ No newline at end of file diff --git a/src/kernel/lib/lib.h b/src/kernel/lib/lib.h new file mode 100644 index 0000000..f0d7d1b --- /dev/null +++ b/src/kernel/lib/lib.h @@ -0,0 +1,18 @@ +#ifndef MELVIX_LIB_H +#define MELVIX_LIB_H + +#include + +size_t strlen(const char *str); + +size_t strcmp(const char *s1, const char *s2); + +char *strcat(char *dst, const char *src); + +void *memory_copy(void *dest, const void *src, size_t count); + +void *memory_set(void *dest, char val, size_t count); + +int memory_compare(const void *a_ptr, const void *b_ptr, size_t size); + +#endif diff --git a/src/kernel/lib/memory.c b/src/kernel/lib/memory.c new file mode 100644 index 0000000..e306ada --- /dev/null +++ b/src/kernel/lib/memory.c @@ -0,0 +1,26 @@ +#include "../graphics/graphics.h" + +void *memory_copy(void *dest, const void *src, size_t count) { + const char *sp = (const char *) src; + char *dp = (char *) dest; + for (; count != 0; count--) *dp++ = *sp++; + return dest; +} + +void *memory_set(void *dest, char val, size_t count) { + char *temp = (char *) dest; + for (; count != 0; count--) *temp++ = val; + return dest; +} + +int memory_compare(const void *a_ptr, const void *b_ptr, size_t size) { + const unsigned char *a = (const unsigned char *) a_ptr; + const unsigned char *b = (const unsigned char *) b_ptr; + for (size_t i = 0; i < size; i++) { + if (a[i] < b[i]) + return -1; + else if (b[i] < a[i]) + return 1; + } + return 0; +} \ No newline at end of file diff --git a/src/kernel/lib/string.c b/src/kernel/lib/string.c new file mode 100644 index 0000000..6ef0316 --- /dev/null +++ b/src/kernel/lib/string.c @@ -0,0 +1,27 @@ +#include + +size_t strlen(const char *str) { + size_t len = 0; + while (str[len]) + len++; + return len; +} + +size_t strcmp(const char *s1, const char *s2) { + while (*s1 && (*s1 == *s2)) { + s1++; + s2++; + } + return *(const unsigned char *) s1 - *(const unsigned char *) s2; +} + +char *strcat(char *dst, const char *src) { + unsigned int i = 0; + unsigned int j = 0; + for (i = 0; dst[i] != 0; i++) {} + for (j = 0; src[j] != 0; j++) { + dst[i + j] = src[j]; + } + dst[i + j] = 0; + return dst; +} diff --git a/src/kernel/linker.ld b/src/kernel/linker.ld new file mode 100644 index 0000000..6461b2b --- /dev/null +++ b/src/kernel/linker.ld @@ -0,0 +1,25 @@ +OUTPUT_FORMAT("binary") +ENTRY(start) +phys = 0x00100000; +SECTIONS +{ + .text phys : AT(phys) { + code = .; + *(.text) + *(.rodata*) + . = ALIGN(4096); + } + .data : AT(phys + (data - code)) + { + data = .; + *(.data) + . = ALIGN(4096); + } + .bss : AT(phys + (bss - code)) + { + bss = .; + *(.bss) + . = ALIGN(4096); + } + end = .; +} diff --git a/src/kernel/sound/frequency.c b/src/kernel/sound/frequency.c new file mode 100644 index 0000000..6d02690 --- /dev/null +++ b/src/kernel/sound/frequency.c @@ -0,0 +1,31 @@ +#include +#include "../io/io.h" +#include "../timer/timer.h" + +static void play_sound(uint32_t frequency) { + uint32_t divided; + uint8_t tmp; + + divided = 1193180 / frequency; + send(0x43, 0xb6); + send(0x42, (uint8_t) (divided)); + send(0x42, (uint8_t) (divided >> 8)); + + tmp = receive(0x61); + if (tmp != (tmp | 3)) { + send(0x61, tmp | 3); + } +} + +static void shut_up() { + uint8_t tmp = receive(0x61) & 0xFC; + + send(0x61, tmp); +} + +//Make a beep +void beep(uint32_t frequency, uint32_t ticks) { + play_sound(frequency); + timer_wait(ticks); + shut_up(); +} \ No newline at end of file diff --git a/src/kernel/sound/sound.h b/src/kernel/sound/sound.h new file mode 100644 index 0000000..baf70b2 --- /dev/null +++ b/src/kernel/sound/sound.h @@ -0,0 +1,6 @@ +#ifndef MELVIX_SOUND_H +#define MELVIX_SOUND_H + +void beep(uint32_t frequency, uint32_t ticks); + +#endif diff --git a/src/kernel/timer/timer.c b/src/kernel/timer/timer.c new file mode 100644 index 0000000..38f5be6 --- /dev/null +++ b/src/kernel/timer/timer.c @@ -0,0 +1,32 @@ +#include "../interrupts/interrupts.h" +#include "../io/io.h" + +volatile unsigned int timer_ticks = 0; + +void timer_phase(int hz) { + int divisor = 1193180 / hz; + send(0x43, 0x36); // 01 10 11 0b // CTR, RW, MODE, BCD + send(0x40, divisor & 0xFF); + send(0x40, divisor >> 8); +} + +// Executed 100 times per second +void timer_handler(struct regs *r) { + timer_ticks++; +} + +// "Delay" function with CPU sleep +void timer_wait(int ticks) { + unsigned int eticks; + + eticks = timer_ticks + ticks; + while (timer_ticks < eticks) { + __asm__ __volatile__ ("sti//hlt//cli"); + } +} + +// Install timer handler into IRQ0 +void timer_install() { + timer_phase(100); + irq_install_handler(0, timer_handler); +} \ No newline at end of file diff --git a/src/kernel/timer/timer.h b/src/kernel/timer/timer.h new file mode 100644 index 0000000..66b3c95 --- /dev/null +++ b/src/kernel/timer/timer.h @@ -0,0 +1,8 @@ +#ifndef MELVIX_TIMER_H +#define MELVIX_TIMER_H + +void timer_install(); + +void timer_wait(int ticks); + +#endif diff --git a/src/lib/lib.h b/src/lib/lib.h deleted file mode 100644 index f0d7d1b..0000000 --- a/src/lib/lib.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef MELVIX_LIB_H -#define MELVIX_LIB_H - -#include - -size_t strlen(const char *str); - -size_t strcmp(const char *s1, const char *s2); - -char *strcat(char *dst, const char *src); - -void *memory_copy(void *dest, const void *src, size_t count); - -void *memory_set(void *dest, char val, size_t count); - -int memory_compare(const void *a_ptr, const void *b_ptr, size_t size); - -#endif diff --git a/src/lib/memory.c b/src/lib/memory.c deleted file mode 100644 index e306ada..0000000 --- a/src/lib/memory.c +++ /dev/null @@ -1,26 +0,0 @@ -#include "../graphics/graphics.h" - -void *memory_copy(void *dest, const void *src, size_t count) { - const char *sp = (const char *) src; - char *dp = (char *) dest; - for (; count != 0; count--) *dp++ = *sp++; - return dest; -} - -void *memory_set(void *dest, char val, size_t count) { - char *temp = (char *) dest; - for (; count != 0; count--) *temp++ = val; - return dest; -} - -int memory_compare(const void *a_ptr, const void *b_ptr, size_t size) { - const unsigned char *a = (const unsigned char *) a_ptr; - const unsigned char *b = (const unsigned char *) b_ptr; - for (size_t i = 0; i < size; i++) { - if (a[i] < b[i]) - return -1; - else if (b[i] < a[i]) - return 1; - } - return 0; -} \ No newline at end of file diff --git a/src/lib/string.c b/src/lib/string.c deleted file mode 100644 index 6ef0316..0000000 --- a/src/lib/string.c +++ /dev/null @@ -1,27 +0,0 @@ -#include - -size_t strlen(const char *str) { - size_t len = 0; - while (str[len]) - len++; - return len; -} - -size_t strcmp(const char *s1, const char *s2) { - while (*s1 && (*s1 == *s2)) { - s1++; - s2++; - } - return *(const unsigned char *) s1 - *(const unsigned char *) s2; -} - -char *strcat(char *dst, const char *src) { - unsigned int i = 0; - unsigned int j = 0; - for (i = 0; dst[i] != 0; i++) {} - for (j = 0; src[j] != 0; j++) { - dst[i + j] = src[j]; - } - dst[i + j] = 0; - return dst; -} diff --git a/src/linker.ld b/src/linker.ld deleted file mode 100644 index 6461b2b..0000000 --- a/src/linker.ld +++ /dev/null @@ -1,25 +0,0 @@ -OUTPUT_FORMAT("binary") -ENTRY(start) -phys = 0x00100000; -SECTIONS -{ - .text phys : AT(phys) { - code = .; - *(.text) - *(.rodata*) - . = ALIGN(4096); - } - .data : AT(phys + (data - code)) - { - data = .; - *(.data) - . = ALIGN(4096); - } - .bss : AT(phys + (bss - code)) - { - bss = .; - *(.bss) - . = ALIGN(4096); - } - end = .; -} diff --git a/src/sound/frequency.c b/src/sound/frequency.c deleted file mode 100644 index 6d02690..0000000 --- a/src/sound/frequency.c +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include "../io/io.h" -#include "../timer/timer.h" - -static void play_sound(uint32_t frequency) { - uint32_t divided; - uint8_t tmp; - - divided = 1193180 / frequency; - send(0x43, 0xb6); - send(0x42, (uint8_t) (divided)); - send(0x42, (uint8_t) (divided >> 8)); - - tmp = receive(0x61); - if (tmp != (tmp | 3)) { - send(0x61, tmp | 3); - } -} - -static void shut_up() { - uint8_t tmp = receive(0x61) & 0xFC; - - send(0x61, tmp); -} - -//Make a beep -void beep(uint32_t frequency, uint32_t ticks) { - play_sound(frequency); - timer_wait(ticks); - shut_up(); -} \ No newline at end of file diff --git a/src/sound/sound.h b/src/sound/sound.h deleted file mode 100644 index baf70b2..0000000 --- a/src/sound/sound.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef MELVIX_SOUND_H -#define MELVIX_SOUND_H - -void beep(uint32_t frequency, uint32_t ticks); - -#endif diff --git a/src/timer/timer.c b/src/timer/timer.c deleted file mode 100644 index 38f5be6..0000000 --- a/src/timer/timer.c +++ /dev/null @@ -1,32 +0,0 @@ -#include "../interrupts/interrupts.h" -#include "../io/io.h" - -volatile unsigned int timer_ticks = 0; - -void timer_phase(int hz) { - int divisor = 1193180 / hz; - send(0x43, 0x36); // 01 10 11 0b // CTR, RW, MODE, BCD - send(0x40, divisor & 0xFF); - send(0x40, divisor >> 8); -} - -// Executed 100 times per second -void timer_handler(struct regs *r) { - timer_ticks++; -} - -// "Delay" function with CPU sleep -void timer_wait(int ticks) { - unsigned int eticks; - - eticks = timer_ticks + ticks; - while (timer_ticks < eticks) { - __asm__ __volatile__ ("sti//hlt//cli"); - } -} - -// Install timer handler into IRQ0 -void timer_install() { - timer_phase(100); - irq_install_handler(0, timer_handler); -} \ No newline at end of file diff --git a/src/timer/timer.h b/src/timer/timer.h deleted file mode 100644 index 66b3c95..0000000 --- a/src/timer/timer.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef MELVIX_TIMER_H -#define MELVIX_TIMER_H - -void timer_install(); - -void timer_wait(int ticks); - -#endif -- cgit v1.2.3