diff --git a/.clang_complete b/.clang_complete new file mode 100644 index 0000000..e69de29 diff --git a/.gdbinit b/.gdbinit new file mode 100644 index 0000000..e69de29 diff --git a/.vs/ClassicOS.sln b/.vs/ClassicOS.sln new file mode 100644 index 0000000..e69de29 diff --git a/.vs/ClassicOS/ClassicOS.sln b/.vs/ClassicOS/ClassicOS.sln new file mode 100644 index 0000000..e69de29 diff --git a/.vs/ClassicOS/v16/.vspscc b/.vs/ClassicOS/v16/.vspscc new file mode 100644 index 0000000..e69de29 diff --git a/.vs/ClassicOS/v16/ClassicOS.suo b/.vs/ClassicOS/v16/ClassicOS.suo new file mode 100644 index 0000000..e69de29 diff --git a/.vscode/settings.json b/.vscode/settings.json index 4e367ac..7ff079b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -93,15 +93,19 @@ "cmake.sourceDirectory": "${workspaceFolder}", "C_Cpp.default.compilerPath": "/usr/bin", "C_Cpp.loggingLevel": "Error", - "C_Cpp.default.enableConfigurationSquiggles": "", - "C_Cpp.default.includePath": "/usr/bin", + "C_Cpp.default.enableConfigurationSquiggles": true, + "C_Cpp.default.includePath": [ + "${workspaceFolder}/**", // Include all files in the workspace folder + "/usr/include", // Standard system include path + "/usr/local/include", // Additional system include path + "/path/to/custom/includes" // Custom include path + ], "workbench.editorAssociations": { - "*.bin": "bin", - "*.c": "c", - "*.h": "c", - "*.cpp": "cpp", - "*.hpp": "hpp", - "*.asm": "asm" + "*.bin": "default", + "*.h": "default", + "*.c": "default", + "*.json": "default", + "*.asm": "default" }, "C_Cpp.default.intelliSenseMode": "linux-clang-x86", "cmake.cmakePath": "/usr/bin/cmake" diff --git a/README.md b/README.md index 4628804..f394ab3 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ An x86 Operating System for 386, 486, Pentium class (P-75, 100, Pentium II, P3, These are the versions I use, but please use the latest possible versions. + NASM version 2.14 QEMU x86_64 GNU ld (GNU Binutils for Debian) 2.31.1 or newer @@ -18,4 +19,4 @@ For C/C++: gcc version 8.3.0 (Debian 8.3.0-6) g++ version 8.3.0 (Debian 8.3.0-6) GNU gdb (Debian 8.2.1-2+b3) 8.2.1 - lldb version 7.0.1 + lldb version 7.0.1 \ No newline at end of file diff --git a/debug.gdb b/debug.gdb new file mode 100644 index 0000000..e69de29 diff --git a/make.config b/make.config new file mode 100644 index 0000000..e69de29 diff --git a/src/kernel/arch/x86/gdt.c b/src/kernel/arch/x86/gdt.c new file mode 100644 index 0000000..7ab0623 --- /dev/null +++ b/src/kernel/arch/x86/gdt.c @@ -0,0 +1,89 @@ +#include "gdt.h" + +// GDT table +struct gdt_entry gdt[3]; + +// GDT pointer +struct gdt_ptr gp; + +// Initialize a GDT entry +void gdt_set_gate(uint32_t num, uint32_t base, uint32_t limit, uint8_t access, + uint8_t gran) +{ + gdt[num].base_low = (base & 0xFFFF); + gdt[num].base_middle = (base >> 16) & 0xFF; + gdt[num].base_high = (base >> 24) & 0xFF; + gdt[num].limit_low = (limit & 0xFFFF); + gdt[num].granularity = (limit >> 16) & 0x0F; + gdt[num].granularity |= gran & 0xF0; + gdt[num].access = access; +} + +// Initialize the GDT +void gdt_init() +{ + // Set up GDT pointer + gp.limit = (sizeof(struct gdt_entry) * 3) - 1; + gp.base = (uint32_t)&gdt; + + // Clear GDT + memset(&gdt, 0, sizeof(gdt)); + + // Set up code segment + gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); + + // Set up data segment + gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); + + // Load GDT + asm volatile("lgdt %0" : : "m"(gp)); +} + +// Exception handlers +extern void divide_error(); +extern void page_fault(); +extern void general_protection_fault(); +extern void double_fault(); + +// Interrupt handlers +extern void system_call(); +extern void timer(); +extern void keyboard(); +extern void device(); + +// ISR table +void (*isr_table[256])(void); + +// Register an ISR +void isr_register(uint8_t num, void (*handler)(void)) +{ + isr_table[num] = handler; +} + +// ISR handler +void isr_handler(struct isr_regs *regs) +{ + void (*handler)(void); + + handler = isr_table[regs->int_no]; + if (handler) + { + handler(); + } +} + +// Initialize the ISR +void isr_init() +{ + // Register exception handlers + isr_register(0, divide_error); + isr_register(14, page_fault); + isr_register(13, general_protection_fault); + isr_register(8, double_fault); + + // Register interrupt handlers + isr_register(0x80, system_call); + isr_register(0x20, timer); + isr_register(0x21, keyboard); + isr_register(0x30, device); +} \ No newline at end of file diff --git a/src/kernel/arch/x86/gdt.h b/src/kernel/arch/x86/gdt.h new file mode 100644 index 0000000..74bfcaf --- /dev/null +++ b/src/kernel/arch/x86/gdt.h @@ -0,0 +1,27 @@ +#ifndef GDT_H +#define GDT_H + +#include + +// GDT entry structure +struct gdt_entry +{ + uint16_t limit_low; // Lower 16 bits of segment limit + uint16_t base_low; // Lower 16 bits of segment base address + uint8_t base_middle; // Middle 8 bits of segment base address + uint8_t access; // Access flags + uint8_t granularity; // Granularity and segment limit flags + uint8_t base_high; // Upper 8 bits of segment base address +} __attribute__((packed)); + +// GDT pointer structure +struct gdt_ptr +{ + uint16_t limit; // Size of GDT in bytes - 1 + uint32_t base; // Address of GDT +} __attribute__((packed)); + +// Initialize the GDT +void gdt_init(); + +#endif \ No newline at end of file diff --git a/src/kernel/arch/x86/idt.c b/src/kernel/arch/x86/idt.c new file mode 100644 index 0000000..e316ac4 --- /dev/null +++ b/src/kernel/arch/x86/idt.c @@ -0,0 +1,55 @@ +#include "idt.h" + +// IDT table +struct idt_entry idt[256]; + +// IDT pointer +struct idt_ptr idtp; + +// Exception handlers +extern void divide_error_handler(); +extern void page_fault_handler(); +extern void general_protection_fault_handler(); +extern void double_fault_handler(); + +// Interrupt handlers +extern void system_call_handler(); +extern void timer_handler(); +extern void keyboard_handler(); +extern void device_handler(); + +// Initialize an IDT entry +void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags) +{ + idt[num].base_lo = base & 0xFFFF; + idt[num].base_hi = (base >> 16) & 0xFFFF; + idt[num].sel = sel; + idt[num].always0 = 0; + idt[num].flags = flags; +} + +// Initialize the IDT +void idt_init() +{ + // Set up IDT pointer + idtp.limit = sizeof(idt) - 1; + idtp.base = (uint32_t)&idt; + + // Clear IDT + memset(&idt, 0, sizeof(idt)); + + // Set up exception handlers + idt_set_gate(0, (uint32_t)divide_error_handler, 0x08, 0x8E); + idt_set_gate(14, (uint32_t)page_fault_handler, 0x08, 0x8E); + idt_set_gate(13, (uint32_t)general_protection_fault_handler, 0x08, 0x8E); + idt_set_gate(8, (uint32_t)double_fault_handler, 0x08, 0x8E); + + // Set up interrupt handlers + idt_set_gate(0x80, (uint32_t)system_call_handler, 0x08, 0xEE); + idt_set_gate(0x20, (uint32_t)timer_handler, 0x08, 0x8E); + idt_set_gate(0x21, (uint32_t)keyboard_handler, 0x08, 0x8E); + idt_set_gate(0x30, (uint32_t)device_handler, 0x08, 0x8E); + + // Load IDT + asm volatile("lidt %0" : : "m"(idtp)); +} \ No newline at end of file diff --git a/src/kernel/arch/x86/idt.h b/src/kernel/arch/x86/idt.h new file mode 100644 index 0000000..b29e14f --- /dev/null +++ b/src/kernel/arch/x86/idt.h @@ -0,0 +1,36 @@ +#ifndef IDT_H +#define IDT_H + +#include + +// IDT entry structure +struct idt_entry { + uint16_t base_lo; // Lower 16 bits of handler function address + uint16_t sel; // Kernel segment selector + uint8_t always0; // Always 0 + uint8_t flags; // Flags + uint16_t base_hi; // Upper 16 bits of handler function address +} __attribute__((packed)); + +// IDT pointer structure +struct idt_ptr { + uint16_t limit; // Size of IDT in bytes - 1 + uint32_t base; // Address of IDT +} __attribute__((packed)); + +// Exception handlers +void divide_error(); +void page_fault(); +void general_protection_fault(); +void double_fault(); + +// Interrupt handlers +void system_call(); +void timer(); +void keyboard(); +void device(); + +// Initialize the IDT +void idt_init(); + +#endif \ No newline at end of file diff --git a/src/kernel/arch/x86/include/memory.h b/src/kernel/arch/x86/include/memory.h new file mode 100644 index 0000000..498a312 --- /dev/null +++ b/src/kernel/arch/x86/include/memory.h @@ -0,0 +1,9 @@ +#ifndef MEMORY_H +#define MEMORY_H + +#include + +void *kmalloc(size_t size); +void kfree(void *ptr); + +#endif /* MEMORY_H */ \ No newline at end of file diff --git a/src/kernel/arch/x86/include/types.h b/src/kernel/arch/x86/include/types.h new file mode 100644 index 0000000..ee2974c --- /dev/null +++ b/src/kernel/arch/x86/include/types.h @@ -0,0 +1,19 @@ +#ifndef TYPES_H +#define TYPES_H + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; + +typedef struct { + uint32_t base; + uint32_t limit; + uint16_t flags; +} gdt_entry_t; + +typedef struct { + uint16_t limit; + uint32_t base; +} idt_entry_t; + +#endif /* TYPES_H */ \ No newline at end of file diff --git a/src/kernel/arch/x86/isr.c b/src/kernel/arch/x86/isr.c new file mode 100644 index 0000000..f589594 --- /dev/null +++ b/src/kernel/arch/x86/isr.c @@ -0,0 +1,64 @@ +#include "isr.h" + +// ISR table +void (*isr_table[256])(struct isr_regs *regs); + +// Register an ISR +void isr_register(uint8_t num, void (*handler)(struct isr_regs *regs)) +{ + isr_table[num] = handler; +} + +// ISR handler +void isr_handler(struct isr_regs *regs) +{ + void (*handler)(struct isr_regs *regs); + + handler = isr_table[regs->int_no]; + if (handler) + { + handler(regs); + } +} + +// Exception handlers +void divide_error() +{ + // Handle divide error exception +} + +void page_fault() +{ + // Handle page fault exception +} + +void general_protection_fault() +{ + // Handle general protection fault exception +} + +void double_fault() +{ + // Handle double fault exception +} + +// Interrupt handlers +void system_call() +{ + // Handle system call interrupt +} + +void timer() +{ + // Handle timer interrupt +} + +void keyboard() +{ + // Handle keyboard interrupt +} + +void device() +{ + // Handle device interrupt +} \ No newline at end of file diff --git a/src/kernel/arch/x86/isr.h b/src/kernel/arch/x86/isr.h new file mode 100644 index 0000000..e733a0d --- /dev/null +++ b/src/kernel/arch/x86/isr.h @@ -0,0 +1,36 @@ +#ifndef ISR_H +#define ISR_H + +#include + +// Structure for storing register values during an ISR +struct isr_regs +{ + uint32_t ds; // Data segment selector + uint32_t edi, esi, ebp, esp, ebx, edx, ecx, + eax; // Pushed by pusha instruction + uint32_t int_no, + err_code; // Interrupt number and error code (if applicable) + uint32_t eip, cs, eflags, useresp, + ss; // Pushed by the processor automatically +}; + +// Register an ISR +void isr_register(uint8_t num, void (*handler)(struct isr_regs *regs)); + +// ISR handler +void isr_handler(struct isr_regs *regs); + +// Exception handlers +void divide_error(); +void page_fault(); +void general_protection_fault(); +void double_fault(); + +// Interrupt handlers +void system_call(); +void timer(); +void keyboard(); +void device(); + +#endif \ No newline at end of file diff --git a/src/kernel/arch/x86/memory/memory.c b/src/kernel/arch/x86/memory/memory.c new file mode 100644 index 0000000..f1efc9d --- /dev/null +++ b/src/kernel/arch/x86/memory/memory.c @@ -0,0 +1,12 @@ +#include "../include/memory.h" + +void *kmalloc(size_t size) +{ + /* TODO: Implement memory allocation */ + return NULL; +} + +void kfree(void *ptr) +{ + /* TODO: Implement memory deallocation */ +} diff --git a/src/kernel/src/types.c b/src/kernel/src/types.c new file mode 100644 index 0000000..6f687ad --- /dev/null +++ b/src/kernel/src/types.c @@ -0,0 +1,17 @@ +#include "../include/types.h" + +void gdt_set_entry(gdt_entry_t *entry, uint32_t base, uint32_t limit, + uint16_t flags) +{ + entry->base = base; + entry->limit = limit; + entry->flags = flags; +} + +void idt_set_entry(idt_entry_t *entry, uint32_t base, uint16_t selector, + uint16_t flags) +{ + entry->base = base; + entry->selector = selector; + entry->flags = flags; +} \ No newline at end of file