diff --git a/CMakeLists.txt b/CMakeLists.txt index 74e30ef..97575b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ set(CMAKE_ASM_COMPILER "i686-elf-as") set(CMAKE_C_COMPILER "i686-elf-gcc") set(CMAKE_CXX_COMPILER "i686-elf-g++") -set(CMAKE_CXX_FLAGS "-ffreestanding -O2 -fno-rtti -Wno-write-strings -Wno-multichar -Wno-unused-parameter -Wno-overflow -Wno-narrowing -fno-exceptions -Wno-trigraphs ${CMAKE_CXX_FLAGS}") +set(CMAKE_CXX_FLAGS "-ffreestanding -funroll-loops -O2 -fno-rtti -Wno-write-strings -Wno-multichar -Wno-unused-parameter -Wno-overflow -Wno-narrowing -fno-exceptions -Wno-trigraphs ${CMAKE_CXX_FLAGS}") set(CMAKE_EXE_LINKER_FLAGS "-T ../linker.ld -ffreestanding -O2 -nostdlib -lgcc -Wwrite-strings ${CMAKE_EXE_LINKER_FLAGS}") include_directories(OwOS "./") diff --git a/build/OwOS.bin b/build/OwOS.bin index a0a9551..6a9a4ee 100755 Binary files a/build/OwOS.bin and b/build/OwOS.bin differ diff --git a/build/OwOS.iso b/build/OwOS.iso index 3d4933f..5876058 100644 Binary files a/build/OwOS.iso and b/build/OwOS.iso differ diff --git a/iso/boot/OwOS.bin b/iso/boot/OwOS.bin index a0a9551..6a9a4ee 100644 Binary files a/iso/boot/OwOS.bin and b/iso/boot/OwOS.bin differ diff --git a/kernel.cpp b/kernel.cpp index a90e20e..60af059 100644 --- a/kernel.cpp +++ b/kernel.cpp @@ -1,9 +1,12 @@ #include #include + #include #include +#include #include +#include #include #include @@ -25,11 +28,14 @@ int kernel_main(uint32_t magic, MultibootInfo_t* multiboot) { // Init systems - int igdt = InitGDT(); - if (igdt == 1) - loggerOK("GDT Loaded"); - else + GDT_Init(); + loggerOK("GDT Init"); + + PIC_Default_Remap(); + loggerOK("PIC Remapped"); + IDT_Init(); + loggerOK("IDT Init"); Nline(); Nline(); Write("OwO, What's This?"); @@ -45,7 +51,7 @@ int kernel_main(uint32_t magic, MultibootInfo_t* multiboot) { SetFGColour(VGA_BRIGHT_MAGENTA); Write("~#"); - PanicKernel(0x00, "Self Triggered Panic", "kernel.cpp:48", "kernel_main(uint32_t magic, MultibootInfo_t* multiboot)"); + // PanicKernel(0x00, "Self Triggered Panic", "kernel.cpp:48", "kernel_main(uint32_t magic, MultibootInfo_t* multiboot)"); for (;;) asm("hlt"); diff --git a/kernel/gdt.cpp b/kernel/gdt.cpp index 755b25d..dd96191 100644 --- a/kernel/gdt.cpp +++ b/kernel/gdt.cpp @@ -25,23 +25,22 @@ void lgdt(GDT_t GDT) { asm ("lgdt %0" : : "m"(GDT)); } -int InitGDT() { +void GDT_Init() { _GDTptr.limit = (sizeof(SegmentDescriptor_t) * 5) - 1; _GDTptr.base = (uint32_t)&_GDT; // Null segment - SetGDTGate(0, 0, 0, 0, 0); - // Code Base 0 limit 32 Access EXEC + RW - SetGDTGate(1, 0x00000000, 0xFFFFFFFF, GDT_ACCESS_PRESENT | GDT_ACCESS_EXEC | GDT_ACCESS_RW, GDT_FLAG_GR_PAGE | GDT_FLAG_SZ_32B); - // Data Base 0 Limit 32 Access RW - SetGDTGate(2, 0x00000000, 0xFFFFFFFF, GDT_ACCESS_PRESENT | GDT_ACCESS_RW, GDT_FLAG_GR_PAGE | GDT_FLAG_SZ_32B); + GDT_Set_Gate(0, 0, 0, 0, 0); + // Code Base 0 limit 32 Access EXEC + RW + GDT_Set_Gate(1, 0x00000000, 0xFFFFFFFF, GDT_ACCESS_PRESENT | GDT_ACCESS_EXEC | GDT_ACCESS_RW, GDT_FLAG_GR_PAGE | GDT_FLAG_SZ_32B); + // Data Base 0 Limit 32 Access RW + GDT_Set_Gate(2, 0x00000000, 0xFFFFFFFF, GDT_ACCESS_PRESENT | GDT_ACCESS_RW, GDT_FLAG_GR_PAGE | GDT_FLAG_SZ_32B); lgdt(_GDTptr); SEGMENTS_RELOAD(); - return 1; } -void SetGDTGate(uint32_t index, uint32_t baseAddr, uint32_t limitAddr, uint8_t accessLvl, uint8_t flags) { +void GDT_Set_Gate(uint32_t index, uint32_t baseAddr, uint32_t limitAddr, uint8_t accessLvl, uint8_t flags) { if (index > 5) return; _GDT[index].base_low = (baseAddr & 0xFFFF); _GDT[index].base_middle = (baseAddr >> 16) & 0xFF; diff --git a/kernel/gdt.h b/kernel/gdt.h index 0b0a08a..2763a01 100644 --- a/kernel/gdt.h +++ b/kernel/gdt.h @@ -19,5 +19,5 @@ extern "C" { extern void SEGMENTS_RELOAD(void); } -int InitGDT(); -void SetGDTGate(uint32_t index, uint32_t baseAddr, uint32_t limitAddr, uint8_t accessLvl, uint8_t flags); +void GDT_Init(); +void GDT_Set_Gate(uint32_t index, uint32_t baseAddr, uint32_t limitAddr, uint8_t accessLvl, uint8_t flags); diff --git a/kernel/idt.cpp b/kernel/idt.cpp index e69de29..8654f5d 100644 --- a/kernel/idt.cpp +++ b/kernel/idt.cpp @@ -0,0 +1,81 @@ +#include "idt.h" + +#include +#include + +struct IDT_Descriptor_t { + uint16_t offset_low; + uint16_t selector; + uint8_t zero; + uint8_t type_attr; + uint16_t offset_high; +} __attribute__((packed)); + +struct IDT_t { + uint16_t limit; + uint32_t base; +} __attribute__((packed)); + + +IDT_Descriptor_t _IDT[256]; +IDT_t _IDTptr; + +void lidt(IDT_t IDT) { + asm("lidt %0" : : "m"(IDT)); +} + +void IDT_Set_Gate(uint8_t i, uint32_t offset, uint16_t selector, uint8_t attrib); + +void IDT_Init() { + _IDTptr.limit = (sizeof(IDT_Descriptor_t) * 256) - 1; + _IDTptr.base = (uint32_t)&_IDT; + + for (uint16_t i = 0; i < 256; i++) + IDT_Set_Gate(i, (uint32_t)&ISR_DEFAULT, 0x01, IDT_ATTR_PRESENT | IDT_TRAP_GATE | IDT_ATTR_PRIV_3); + + IDT_Set_Gate(0x00, (uint32_t)&ISR0, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + IDT_Set_Gate(0x01, (uint32_t)&ISR1, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + IDT_Set_Gate(0x02, (uint32_t)&ISR2, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + IDT_Set_Gate(0x03, (uint32_t)&ISR3, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + IDT_Set_Gate(0x04, (uint32_t)&ISR4, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + IDT_Set_Gate(0x05, (uint32_t)&ISR5, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + IDT_Set_Gate(0x06, (uint32_t)&ISR6, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + IDT_Set_Gate(0x07, (uint32_t)&ISR7, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + IDT_Set_Gate(0x08, (uint32_t)&ISR8, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + IDT_Set_Gate(0x09, (uint32_t)&ISR9, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + IDT_Set_Gate(0x0A, (uint32_t)&ISR10, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + IDT_Set_Gate(0x0B, (uint32_t)&ISR11, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + IDT_Set_Gate(0x0C, (uint32_t)&ISR12, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + IDT_Set_Gate(0x0D, (uint32_t)&ISR13, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + IDT_Set_Gate(0x0E, (uint32_t)&ISR14, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + IDT_Set_Gate(0x0F, (uint32_t)&ISR15, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + IDT_Set_Gate(0x10, (uint32_t)&ISR16, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + IDT_Set_Gate(0x11, (uint32_t)&ISR17, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + IDT_Set_Gate(0x12, (uint32_t)&ISR18, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + IDT_Set_Gate(0x13, (uint32_t)&ISR19, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + IDT_Set_Gate(0x14, (uint32_t)&ISR20, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + IDT_Set_Gate(0x15, (uint32_t)&ISR21, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + IDT_Set_Gate(0x16, (uint32_t)&ISR22, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + IDT_Set_Gate(0x17, (uint32_t)&ISR23, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + IDT_Set_Gate(0x18, (uint32_t)&ISR24, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + IDT_Set_Gate(0x19, (uint32_t)&ISR25, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + IDT_Set_Gate(0x1A, (uint32_t)&ISR26, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + IDT_Set_Gate(0x1B, (uint32_t)&ISR27, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + IDT_Set_Gate(0x1C, (uint32_t)&ISR28, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + IDT_Set_Gate(0x1D, (uint32_t)&ISR29, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + IDT_Set_Gate(0x1E, (uint32_t)&ISR30, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + IDT_Set_Gate(0x1F, (uint32_t)&ISR31, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + + IDT_Set_Gate(0x21, (uint32_t)&ISR_KBD, 0x01, IDT_ATTR_PRESENT | IDT_INT_GATE); + + lidt(_IDTptr); +} + +void IDT_Set_Gate(uint8_t i, uint32_t offset, uint16_t selector, uint8_t attrib) { + if (i > 256) return; + _IDT[i].offset_low = offset & 0xFFFF; + _IDT[i].selector = selector * 8; + _IDT[i].zero = 0; + _IDT[i].type_attr = attrib; + _IDT[i].offset_high = (offset & 0xFFFF) >> 16; +} diff --git a/kernel/idt.h b/kernel/idt.h index e69de29..6bfd739 100644 --- a/kernel/idt.h +++ b/kernel/idt.h @@ -0,0 +1,55 @@ +#pragma once + +#include + +#define IDT_ATTR_PRESENT 0x80 +#define IDT_ATTR_PRIV_3 0x60 +#define IDT_ATTR_PRIV_2 0x40 +#define IDT_ATTR_PRIV_1 0x20 +#define IDT_INT_GATE 0x0E +#define IDT_TRAP_GATE 0x0F +#define IDT_TASK_GATE 0x15 + + +void IDT_Init(); +void IDT_Set_Gate(); + +#define ISR_DEF(id) extern void ISRid(void) + +extern "C" { + extern void ISR_DEFAULT(void); + extern void ISR_KBD(void); + + extern void ISR0(void); + extern void ISR1(void); + extern void ISR2(void); + extern void ISR3(void); + extern void ISR4(void); + extern void ISR5(void); + extern void ISR6(void); + extern void ISR7(void); + extern void ISR8(void); + extern void ISR9(void); + extern void ISR10(void); + extern void ISR11(void); + extern void ISR12(void); + extern void ISR13(void); + extern void ISR14(void); + extern void ISR15(void); + extern void ISR16(void); + extern void ISR17(void); + extern void ISR18(void); + extern void ISR19(void); + extern void ISR20(void); + extern void ISR21(void); + extern void ISR22(void); + extern void ISR23(void); + extern void ISR24(void); + extern void ISR25(void); + extern void ISR26(void); + extern void ISR27(void); + extern void ISR28(void); + extern void ISR29(void); + extern void ISR30(void); + extern void ISR31(void); +} diff --git a/kernel/isr.asm b/kernel/isr.asm new file mode 100644 index 0000000..12c908c --- /dev/null +++ b/kernel/isr.asm @@ -0,0 +1,272 @@ +.align 4 +.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 + +ISR0: + cli + push $0 + push $0 + jmp ISR_FAULT + +ISR1: + cli + push $0 + push $1 + jmp ISR_FAULT + +ISR2: + cli + push $0 + push $2 + jmp ISR_FAULT + +ISR3: + cli + push $0 + push $3 + jmp ISR_FAULT + +ISR4: + cli + push $0 + push $4 + jmp ISR_FAULT + +ISR5: + cli + push $0 + push $5 + jmp ISR_FAULT + +ISR6: + cli + push $0 + push $6 + jmp ISR_FAULT + +ISR7: + cli + push $0 + push $7 + jmp ISR_FAULT + +ISR8: + cli + push $8 + jmp ISR_FAULT + +ISR9: + cli + push $9 + jmp ISR_FAULT + +ISR10: + cli + push $10 + jmp ISR_FAULT + +ISR11: + cli + push $11 + jmp ISR_FAULT + +ISR12: + cli + push $12 + jmp ISR_FAULT + +ISR13: + cli + push $13 + jmp ISR_FAULT + +ISR14: + cli + push $14 + jmp ISR_FAULT + +ISR15: + cli + push $15 + jmp ISR_FAULT + +ISR16: + cli + push $16 + jmp ISR_FAULT + +ISR17: + cli + push $17 + jmp ISR_FAULT + +ISR18: + cli + push $18 + jmp ISR_FAULT + +ISR19: + cli + push $19 + jmp ISR_FAULT + +ISR20: + cli + push $20 + jmp ISR_FAULT + +ISR21: + cli + push $21 + jmp ISR_FAULT + +ISR22: + cli + push $22 + jmp ISR_FAULT + +ISR23: + cli + push $23 + jmp ISR_FAULT + +ISR24: + cli + push $24 + jmp ISR_FAULT + +ISR25: + cli + push $25 + jmp ISR_FAULT + +ISR26: + cli + push $26 + jmp ISR_FAULT + +ISR27: + cli + push $27 + jmp ISR_FAULT + +ISR28: + cli + push 28 + jmp ISR_FAULT + +ISR29: + cli + push $29 + jmp ISR_FAULT + +ISR30: + cli + push $30 + jmp ISR_FAULT + +ISR31: + cli + push $31 + jmp ISR_FAULT + +.extern FaultHandler +ISR_FAULT: + pusha + push %ds + push %es + push %fs + push %gs + movw $0x10,%ax + movw %ax,%ds + movw %ax,%es + movw %ax,%fs + movw %ax,%gs + movl %esp,%eax + pushl %eax + call FaultHandler + popl %eax + popl %gs + popl %fs + popl %es + popl %ds + popa + addl $8,%esp + iret + +.global ISR_DEFAULT +.extern DEFAULT_ISR +ISR_DEFAULT: + pushal + pushw %ds + pushw %es + pushw %fs + pushw %gs + pushl %ebx + movw $0x10,%bx + movw %bx,%ds + popl %ebx + + cld /* C code following the sysV ABI requires DF to be clear on function entry */ + call DEFAULT_ISR + + popw %gs + popw %fs + popw %es + popw %ds + popal + iret + +.global ISR_KBD +.extern KeyboardHandler +ISR_KBD: + pushal + pushw %ds + pushw %es + pushw %fs + pushw %gs + pushl %ebx + movw $0x10,%bx + movw %bx,%ds + popl %ebx + + cld /* C code following the sysV ABI requires DF to be clear on function entry */ + call KeyboardHandler + + popw %gs + popw %fs + popw %es + popw %ds + popal + iret + diff --git a/kernel/isr.cpp b/kernel/isr.cpp new file mode 100644 index 0000000..45fdf30 --- /dev/null +++ b/kernel/isr.cpp @@ -0,0 +1,68 @@ + +#include +#include +#include + +struct Regs_t { + unsigned int gs, fs, es, ds; /* pushed the segs last */ + unsigned int edi, esi, ebp, esp, ebx, edx, ecx, eax; /* pushed by 'pusha' */ + unsigned int int_no, err_code; /* our 'push byte #' and ecodes do this */ + unsigned int eip, cs, eflags, useresp, ss; /* pushed by the processor automatically */ +}; + +char *PanicMessage[] = { + "Division By Zero", + "Debug", + "Non Maskable Interrupt", + "Break Point", + "Into Detect Overflow", + "Out of bounds Exception", + "Invalid Opcode", + "No Coprocessor", + "Double Fault", + "Coprocessor Segment Overrun", + "Bad TSS Exception", + "Segment not present", + "Stack Fault", + "General Protection Fault", + "Page Fault", + "Unknown Interrupt", + "Coprocessor Fault", + "Alignement Check Exception", + "Machine Check Exception", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved" +}; + +extern "C" { + +void DEFAULT_ISR() { + Write("SMH \n"); + outb(0x20,0x20); +} + +void KeyboardHandler() { + Write("Keyboard Pressed! \n"); + outb(0x20,0x20); +} + +void FaultHandler(struct Regs_t *r) { + uint32_t val; + asm volatile ( "mov %%cr2, %0" : "=r"(val) ); + PanicKernel(val, PanicMessage[r->int_no]); + for (;;) + asm("hlt"); +} + +} diff --git a/kernel/kernio.h b/kernel/kernio.h index 440fdd0..da9ef25 100644 --- a/kernel/kernio.h +++ b/kernel/kernio.h @@ -38,8 +38,7 @@ static inline void outl(uint16_t port, uint32_t val) { asm ( "outl %0, %1" : : "a"(val), "Nd"(port) ); } -static inline void io_wait(void) { - /* TODO: This is probably fragile. */ +static inline void io_wait() { asm ( "jmp 1f\n\t" "1:jmp 2f\n\t" "2:" ); diff --git a/kernel/pic.cpp b/kernel/pic.cpp new file mode 100644 index 0000000..42238ba --- /dev/null +++ b/kernel/pic.cpp @@ -0,0 +1,53 @@ +#include "pic.h" + +#include + +void PIC_Default_Remap() { + outb(0x20, 0x11); + io_wait(); + outb(0xA0, 0x11); + io_wait(); + outb(0x21, 0x20); + io_wait(); + outb(0xA1, 0x28); + io_wait(); + outb(0x21, 0x04); + io_wait(); + outb(0xA1, 0x02); + io_wait(); + outb(0x21, 0x01); + io_wait(); + outb(0xA1, 0x01); + io_wait(); + outb(0x21, 0x0); + io_wait(); + outb(0xA1, 0x0); +} + +void PIC_Remap(int offset1, int offset2) { + unsigned char a1, a2; + + a1 = inb(PIC1_DATA); // save masks + a2 = inb(PIC2_DATA); + + outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4); // starts the initialization sequence (in cascade mode) + io_wait(); + outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4); + io_wait(); + outb(PIC1_DATA, offset1); // ICW2: Master PIC vector offset + io_wait(); + outb(PIC2_DATA, offset2); // ICW2: Slave PIC vector offset + io_wait(); + outb(PIC1_DATA, 4); // ICW3: tell Master PIC that there is a slave PIC at IRQ2 (0000 0100) + io_wait(); + outb(PIC2_DATA, 2); // ICW3: tell Slave PIC its cascade identity (0000 0010) + io_wait(); + + outb(PIC1_DATA, ICW4_8086); + io_wait(); + outb(PIC2_DATA, ICW4_8086); + io_wait(); + + outb(PIC1_DATA, a1); // restore saved masks. + outb(PIC2_DATA, a2); +} diff --git a/kernel/pic.h b/kernel/pic.h new file mode 100644 index 0000000..9ad06eb --- /dev/null +++ b/kernel/pic.h @@ -0,0 +1,25 @@ +#pragma once + +#define PIC1 0x20 /* IO base address for master PIC */ +#define PIC2 0xA0 /* IO base address for slave PIC */ +#define PIC1_COMMAND PIC1 +#define PIC1_DATA (PIC1+1) +#define PIC2_COMMAND PIC2 +#define PIC2_DATA (PIC2+1) + +#define PIC_EOI 0x20 /* End-of-interrupt command code */ + +#define ICW1_ICW4 0x01 /* ICW4 (not) needed */ +#define ICW1_SINGLE 0x02 /* Single (cascade) mode */ +#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */ +#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */ +#define ICW1_INIT 0x10 /* Initialization - required! */ + +#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */ +#define ICW4_AUTO 0x02 /* Auto (normal) EOI */ +#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */ +#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */ +#define ICW4_SFNM 0x10 /* Special fully nested (not) */ + +void PIC_Default_Remap(); +void PIC_Remap(int offset1, int offset2);