diff --git a/.gitignore b/.gitignore index b302462..a9e2c49 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,6 @@ *.bin *.ini *.out +*.pdf +*.aux +*.gz diff --git a/build_numbers.c b/build_numbers.c index 490d9e0..cd99e5f 100644 --- a/build_numbers.c +++ b/build_numbers.c @@ -1,3 +1,3 @@ #ifndef KERNEL_VERSION_NUMBER -#define KERNEL_VERSION_NUMBER "0.0.1-354" +#define KERNEL_VERSION_NUMBER "0.0.3-0" #endif diff --git a/includes/idt.h b/includes/idt.h new file mode 100644 index 0000000..961eefd --- /dev/null +++ b/includes/idt.h @@ -0,0 +1,21 @@ +#ifndef IDT_H +#define IDT_H +struct idt_entry +{ + unsigned short base_lo; + unsigned short sel; /* Our kernel segment goes here. */ + unsigned char always0; + unsigned char flags; + unsigned short base_hi; +} __attribute__((packed)); + +struct idt_ptr +{ + unsigned short size; + struct idt_entry* idt_entries_start; +} __attribute__((packed)); + +void install_idt(void); +void idt_set_gate(struct idt_entry*, unsigned long, unsigned short, unsigned char); +void load_idt(struct idt_ptr*); +#endif diff --git a/includes/interrupt_handler.h b/includes/interrupt_handler.h new file mode 100644 index 0000000..3be8077 --- /dev/null +++ b/includes/interrupt_handler.h @@ -0,0 +1,46 @@ +#ifndef INTERRUPT_HANDLER_H +#define INTERRUPT_HANDLER_H + +struct isr_state +{ + unsigned int gs, fs, es, ds; // The segement registers pushed last + unsigned int edi, esi, edp, esp, ebx, eax; // Pushed by pusha + unsigned int int_no, error; // Data pushed by the 'isr#' routines. + unsigned int eip, cs, eflags, useresp, ss; // Pushed by the processor +}; + +void interrupt_handler(struct isr_state); +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(); + +#endif diff --git a/includes/loader.h b/includes/loader.h new file mode 100644 index 0000000..2f64c29 --- /dev/null +++ b/includes/loader.h @@ -0,0 +1,11 @@ +#ifndef LOADER_H +#define LOADER_H + +struct multiboot_header +{ + unsigned long magic; + unsigned long flags; + unsigned long checksum; +}; + +#endif diff --git a/includes/serial.h b/includes/serial.h index 8ddcd6c..b82dc79 100644 --- a/includes/serial.h +++ b/includes/serial.h @@ -20,4 +20,5 @@ void set_serial_baud_rate(unsigned short, unsigned short); void configure_serial_line(unsigned short); int serial_transmit_fifo_empty(unsigned int); +void write_to_com(unsigned int, char*); #endif diff --git a/kernel/gdt.c b/kernel/gdt.c index e527bc3..0c7b57a 100644 --- a/kernel/gdt.c +++ b/kernel/gdt.c @@ -1,6 +1,7 @@ #include "../includes/gdt.h" /* Code taken from http://www.osdever.net/bkerndev/Docs/gdt.htm with some minor tweaks. */ - +struct gdt_entry gdt_entries[3]; +struct gdt gdt_ptr; /* Should be called by main. This will setup the special GDT * pointer, set up the first 3 entries in our GDT, and then * finally call load_gdt() in our assembler file in order @@ -8,8 +9,6 @@ * new segment registers */ void gdt_install() { - struct gdt_entry gdt_entries[3]; - struct gdt gdt_ptr; /* Setup the GDT pointer and the size of the table */ gdt_ptr.size = sizeof(struct gdt_entry) * 3 - 1; gdt_ptr.address = (unsigned int) &gdt_entries; diff --git a/kernel/idt.c b/kernel/idt.c new file mode 100644 index 0000000..78f7bd1 --- /dev/null +++ b/kernel/idt.c @@ -0,0 +1,56 @@ +#include "../includes/idt.h" +#include "../includes/interrupt_handler.h" + +struct idt_entry idt_entries[256]; +struct idt_ptr idt; + +void idt_install() +{ + idt.size = (sizeof (struct idt_entry) * 256) - 1; + idt.idt_entries_start = (struct idt_entry *) &idt_entries; + + idt_set_gate(&idt_entries[0], (unsigned int) isr0, 0x08, 0x8E); + idt_set_gate(&idt_entries[1], (unsigned int) isr1, 0x08, 0x8E); + idt_set_gate(&idt_entries[2], (unsigned int) isr2, 0x08, 0x8E); + idt_set_gate(&idt_entries[3], (unsigned int) isr3, 0x08, 0x8E); + idt_set_gate(&idt_entries[4], (unsigned int) isr4, 0x08, 0x8E); + idt_set_gate(&idt_entries[5], (unsigned int) isr5, 0x08, 0x8E); + idt_set_gate(&idt_entries[6], (unsigned int) isr6, 0x08, 0x8E); + idt_set_gate(&idt_entries[7], (unsigned int) isr7, 0x08, 0x8E); + idt_set_gate(&idt_entries[8], (unsigned int) isr8, 0x08, 0x8E); + idt_set_gate(&idt_entries[9], (unsigned int) isr9, 0x08, 0x8E); + idt_set_gate(&idt_entries[10], (unsigned int) isr10, 0x08, 0x8E); + idt_set_gate(&idt_entries[11], (unsigned int) isr11, 0x08, 0x8E); + idt_set_gate(&idt_entries[12], (unsigned int) isr12, 0x08, 0x8E); + idt_set_gate(&idt_entries[13], (unsigned int) isr13, 0x08, 0x8E); + idt_set_gate(&idt_entries[14], (unsigned int) isr14, 0x08, 0x8E); + idt_set_gate(&idt_entries[15], (unsigned int) isr15, 0x08, 0x8E); + idt_set_gate(&idt_entries[16], (unsigned int) isr16, 0x08, 0x8E); + idt_set_gate(&idt_entries[17], (unsigned int) isr17, 0x08, 0x8E); + idt_set_gate(&idt_entries[18], (unsigned int) isr18, 0x08, 0x8E); + idt_set_gate(&idt_entries[19], (unsigned int) isr19, 0x08, 0x8E); + idt_set_gate(&idt_entries[20], (unsigned int) isr20, 0x08, 0x8E); + idt_set_gate(&idt_entries[21], (unsigned int) isr21, 0x08, 0x8E); + idt_set_gate(&idt_entries[22], (unsigned int) isr22, 0x08, 0x8E); + idt_set_gate(&idt_entries[23], (unsigned int) isr23, 0x08, 0x8E); + idt_set_gate(&idt_entries[24], (unsigned int) isr24, 0x08, 0x8E); + idt_set_gate(&idt_entries[25], (unsigned int) isr25, 0x08, 0x8E); + idt_set_gate(&idt_entries[26], (unsigned int) isr26, 0x08, 0x8E); + idt_set_gate(&idt_entries[27], (unsigned int) isr27, 0x08, 0x8E); + idt_set_gate(&idt_entries[28], (unsigned int) isr28, 0x08, 0x8E); + idt_set_gate(&idt_entries[29], (unsigned int) isr29, 0x08, 0x8E); + idt_set_gate(&idt_entries[30], (unsigned int) isr30, 0x08, 0x8E); + idt_set_gate(&idt_entries[31], (unsigned int) isr31, 0x08, 0x8E); + //asm("xchg %bx, %bx"); + load_idt(&idt); +} + +void idt_set_gate(struct idt_entry* entry, unsigned long base, unsigned short sel, unsigned char flags) +{ + entry->base_lo = (base & 0xFFFF); + entry->base_hi = (base >> 16) & 0xFFFF; + + entry->sel = sel; + entry->always0 = 0; + entry->flags = flags; +} diff --git a/kernel/interrupt_handler.c b/kernel/interrupt_handler.c new file mode 100644 index 0000000..4178c8a --- /dev/null +++ b/kernel/interrupt_handler.c @@ -0,0 +1,7 @@ +#include "../includes/interrupt_handler.h" +#include "../includes/serial.h" + +void interrupt_handler(struct isr_state stack) +{ + write_to_com(COM1_PORT, "Interrupt detected!\n"); +} diff --git a/kernel/interrupt_service_routines.s b/kernel/interrupt_service_routines.s new file mode 100644 index 0000000..68df897 --- /dev/null +++ b/kernel/interrupt_service_routines.s @@ -0,0 +1,277 @@ +global isr0 ; division by zero +global isr1 ; debug exception +global isr2 ; Non-maskable interrupt +global isr3 ; Breakpoint exception +global isr4 ; Into detected overflow exception +global isr5 ; Out of bounds exception +global isr6 ; Invalid opcode exception +global isr7 ; No co-processor exception +global isr8 ; Double fault exception +global isr9 ; Co-processor segment overrun exception +global isr10 ; Bad TSS exception +global isr11 ; Segment not present +global isr12 ; Stack fault exception +global isr13 ; General protection fault +global isr14 ; Page fault exception +global isr15 ; Unkown interrupt exception +global isr16 ; Co-processor fault exception +global isr17 ; Alignment check exception +global isr18 ; Machine check exception +global isr19 ; Reserved +global isr20 +global isr21 +global isr22 +global isr23 +global isr24 +global isr25 +global isr26 +global isr27 +global isr28 +global isr29 +global isr30 +global isr31 ; reserved + +isr0: ; division by zero + cli + push byte 0 ; This doesn't produce an error code, so push a dummy code + ; to the stack. This keeps the stack uniform when calling the common interrupt stub. + push byte 0 ; Push the interrupt number to the stack + jmp isr_common_stub + +isr1: ; debug exception + cli + push byte 0 ; This doesn't produce an error code, so push a dummy code + ; to the stack. This keeps the stack uniform when calling the common interrupt stub. + push byte 1 ; Push the interrupt number to the stack + jmp isr_common_stub + +isr2: ; Non-maskable interrupt + cli + push byte 0 ; This doesn't produce an error code, so push a dummy code + ; to the stack. This keeps the stack uniform when calling the common interrupt stub. + push byte 2 ; Push the interrupt number to the stack + jmp isr_common_stub + +isr3: ; Breakpoint exception + cli + push byte 0 ; This doesn't produce an error code, so push a dummy code + ; to the stack. This keeps the stack uniform when calling the common interrupt stub. + push byte 3 ; Push the interrupt number to the stack + jmp isr_common_stub + +isr4: ; Into detected overflow exception + cli + push byte 0 ; This doesn't produce an error code, so push a dummy code + ; to the stack. This keeps the stack uniform when calling the common interrupt stub. + push byte 4 ; Push the interrupt number to the stack + jmp isr_common_stub + +isr5: ; Out of bounds exception + cli + push byte 0 ; This doesn't produce an error code, so push a dummy code + ; to the stack. This keeps the stack uniform when calling the common interrupt stub. + push byte 5 ; Push the interrupt number to the stack + jmp isr_common_stub + +isr6: ; Invalid opcode exception + cli + push byte 0 ; This doesn't produce an error code, so push a dummy code + ; to the stack. This keeps the stack uniform when calling the common interrupt stub. + push byte 6 ; Push the interrupt number to the stack + jmp isr_common_stub + +isr7: ; No co-processor exception + cli + push byte 0 ; This doesn't produce an error code, so push a dummy code + ; to the stack. This keeps the stack uniform when calling the common interrupt stub. + push byte 7 ; Push the interrupt number to the stack + jmp isr_common_stub + +isr8: ; Double fault exception + cli + ; This interrupt pushes an error code, so we only need to push its number. + push byte 8 ; Push the interrupt number to the stack + jmp isr_common_stub + +isr9: ; Co-processor segment overrun exception + cli + push byte 0 ; This doesn't produce an error code, so push a dummy code + ; to the stack. This keeps the stack uniform when calling the common interrupt stub. + push byte 9 ; Push the interrupt number to the stack + jmp isr_common_stub + +isr10: ; Bad TSS exception + cli + ; This interrupt pushes an error code, so we only need to push its number. + push byte 10 ; Push the interrupt number to the stack + jmp isr_common_stub + +isr11: ; Segment not present + cli + ; This interrupt pushes an error code, so we only need to push its number. + push byte 11 ; Push the interrupt number to the stack + jmp isr_common_stub + +isr12: ; Stack fault exception + cli + ; This interrupt pushes an error code, so we only need to push its number. + push byte 12 ; Push the interrupt number to the stack + jmp isr_common_stub + +isr13: ; General protection fault + cli + ; This interrupt pushes an error code, so we only need to push its number. + push byte 13 ; Push the interrupt number to the stack + jmp isr_common_stub + +isr14: ; Page fault exception + cli + ; This interrupt pushes an error code, so we only need to push its number. + push byte 14 ; Push the interrupt number to the stack + jmp isr_common_stub + +isr15: ; Unkown interrupt exception + cli + push byte 0 ; This doesn't produce an error code, so push a dummy code + ; to the stack. This keeps the stack uniform when calling the common interrupt stub. + push byte 15 ; Push the interrupt number to the stack + jmp isr_common_stub + +isr16: ; Co-processor fault exception + cli + push byte 0 ; This doesn't produce an error code, so push a dummy code + ; to the stack. This keeps the stack uniform when calling the common interrupt stub. + push byte 16 ; Push the interrupt number to the stack + jmp isr_common_stub + +isr17: ; Alignment check exception + cli + push byte 0 ; This doesn't produce an error code, so push a dummy code + ; to the stack. This keeps the stack uniform when calling the common interrupt stub. + push byte 17 ; Push the interrupt number to the stack + jmp isr_common_stub + +isr18: ; Machine check exception + cli + push byte 0 ; This doesn't produce an error code, so push a dummy code + ; to the stack. This keeps the stack uniform when calling the common interrupt stub. + push byte 18 ; Push the interrupt number to the stack + jmp isr_common_stub + +isr19: ; Reserved + cli + push byte 0 ; This doesn't produce an error code, so push a dummy code + ; to the stack. This keeps the stack uniform when calling the common interrupt stub. + push byte 19 ; Push the interrupt number to the stack + jmp isr_common_stub + +isr20: + cli + push byte 0 ; This doesn't produce an error code, so push a dummy code + ; to the stack. This keeps the stack uniform when calling the common interrupt stub. + push byte 20 ; Push the interrupt number to the stack + jmp isr_common_stub + +isr21: + cli + push byte 0 ; This doesn't produce an error code, so push a dummy code + ; to the stack. This keeps the stack uniform when calling the common interrupt stub. + push byte 21 ; Push the interrupt number to the stack + jmp isr_common_stub + +isr22: + cli + push byte 0 ; This doesn't produce an error code, so push a dummy code + ; to the stack. This keeps the stack uniform when calling the common interrupt stub. + push byte 22 ; Push the interrupt number to the stack + jmp isr_common_stub + +isr23: + cli + push byte 0 ; This doesn't produce an error code, so push a dummy code + ; to the stack. This keeps the stack uniform when calling the common interrupt stub. + push byte 23 ; Push the interrupt number to the stack + jmp isr_common_stub + +isr24: + cli + push byte 0 ; This doesn't produce an error code, so push a dummy code + ; to the stack. This keeps the stack uniform when calling the common interrupt stub. + push byte 24 ; Push the interrupt number to the stack + jmp isr_common_stub + +isr25: + cli + push byte 0 ; This doesn't produce an error code, so push a dummy code + ; to the stack. This keeps the stack uniform when calling the common interrupt stub. + push byte 25 ; Push the interrupt number to the stack + jmp isr_common_stub + +isr26: + cli + push byte 0 ; This doesn't produce an error code, so push a dummy code + ; to the stack. This keeps the stack uniform when calling the common interrupt stub. + push byte 26 ; Push the interrupt number to the stack + jmp isr_common_stub + +isr27: + cli + push byte 0 ; This doesn't produce an error code, so push a dummy code + ; to the stack. This keeps the stack uniform when calling the common interrupt stub. + push byte 27 ; Push the interrupt number to the stack + jmp isr_common_stub + +isr28: + cli + push byte 0 ; This doesn't produce an error code, so push a dummy code + ; to the stack. This keeps the stack uniform when calling the common interrupt stub. + push byte 28 ; Push the interrupt number to the stack + jmp isr_common_stub + +isr29: + cli + push byte 0 ; This doesn't produce an error code, so push a dummy code + ; to the stack. This keeps the stack uniform when calling the common interrupt stub. + push byte 29 ; Push the interrupt number to the stack + jmp isr_common_stub + +isr30: + cli + push byte 0 ; This doesn't produce an error code, so push a dummy code + ; to the stack. This keeps the stack uniform when calling the common interrupt stub. + push byte 30 ; Push the interrupt number to the stack + jmp isr_common_stub + +isr31: ; reserved + cli + push byte 0 ; This doesn't produce an error code, so push a dummy code + ; to the stack. This keeps the stack uniform when calling the common interrupt stub. + push byte 31 ; Push the interrupt number to the stack + jmp isr_common_stub + +extern interrupt_handler + +isr_common_stub: + pusha ; Registers are pushed in this order: AX, CX, DX, BX, SP, BP, SI, DI + push ds + push es + push fs + push gs + + mov ax, 0x10 ; Load the Kernel Data Segment descriptor + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov eax, esp ; Push the stack pointer + push eax + mov eax, interrupt_handler + call eax ; A special call, preserves the 'eip' register + pop eax + pop gs + pop fs + pop es + pop ds + popa + add esp, 8 ; Cleans up the pushed error code and pushed ISR number + iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP! diff --git a/kernel/io.s b/kernel/io.s index a7416d0..823580a 100644 --- a/kernel/io.s +++ b/kernel/io.s @@ -38,3 +38,13 @@ load_gdt: return: ret ; Now we've changed CS to 0x08 + +global load_idt + +; load_idt - Installs the IDT +; stack: [esp + 4] The address of the IDT +; [esp ] The return address +load_idt: + mov eax, [esp + 4] + lidt [eax] + ret diff --git a/kernel/kmain.c b/kernel/kmain.c index 933f7e5..2fb4ee5 100644 --- a/kernel/kmain.c +++ b/kernel/kmain.c @@ -1,7 +1,11 @@ #include "../includes/io.h" #include "../includes/gdt.h" +#include "../includes/idt.h" #include "../includes/serial.h" #include "../includes/screen.h" +#include "../includes/loader.h" + +struct multiboot_header header __attribute((section(".multiboot"))) = (struct multiboot_header) {.magic = 0x1BADB002, .flags = 0x1, .checksum = -464367619}; void kmain() { @@ -39,9 +43,15 @@ void kmain() draw_string("Installing GDT...\n", 0xF, 0x0); write_to_com(COM1_PORT, "Installing the GDT.\n"); gdt_install(); - move_cursor(0, 4); - write_to_com(COM1_PORT, "GDT installed.\n"); - draw_string("Installed GDT\n", 0xf, 0x0); - + + //move_cursor(0, 4); + //asm("xchg %bx, %bx"); + //write_to_com(COM1_PORT, "GDT installed.\n"); + //asm("xchg %bx, %bx"); // Boch's break point + //draw_string("Installed GDT\n", 0xf, 0x0); + //asm("xchg %bx, %bx"); + idt_install(); + write_to_com(COM1_PORT, "IDT installed.\n"); + int i = 5 / 0; asm("hlt"); } diff --git a/kernel/loader.s b/kernel/loader.s index b2c0a76..343cbf9 100644 --- a/kernel/loader.s +++ b/kernel/loader.s @@ -1,16 +1,8 @@ global loader -align 4 -MAGIC_NUMBER equ 0x1BADB002 -FLAGS equ 0x0 -CHECKSUM equ -MAGIC_NUMBER -KERNEL_STACK_SIZE equ 4096 ; size of stack in bytes - - dd MAGIC_NUMBER - dd FLAGS - dd CHECKSUM - +align 8 loader: + KERNEL_STACK_SIZE equ 8192 mov esp, kernel_stack; + KERNEL_STACK_SIZE ; ont ESP to the start of the stack (end of memory area) extern kmain call kmain diff --git a/support_files/boch.txt b/support_files/boch.txt index b1f6326..8948249 100644 --- a/support_files/boch.txt +++ b/support_files/boch.txt @@ -1,5 +1,4 @@ megs: 32 -display_library: x, options = "gui_debug" romimage: file=/usr/share/bochs/BIOS-bochs-latest vgaromimage: file=/usr/share/bochs/VGABIOS-lgpl-latest ata0-master: type=cdrom, path=kernel.iso, status=inserted @@ -8,3 +7,4 @@ log: bochs.log clock: sync=realtime, time0=local cpu: count=1, ips=1000000 com1: enabled=1, mode=file, dev=com1.out +magic_break: enabled=1 diff --git a/support_files/link.ld b/support_files/link.ld index 53bd227..20c9634 100644 --- a/support_files/link.ld +++ b/support_files/link.ld @@ -5,6 +5,7 @@ SECTIONS { .text ALIGN (0x1000) : { + KEEP(*(.multiboot)) *(.text) }