Wed, 27 Dec 2017 00:51:39 +0100
6 files changed,
110 insertions(+),
9 deletions(-)
M
README.md
→
README.md
@@ -3,7 +3,7 @@ Simple x86 operating system written in assembly and C.
## Software Requirements * GNU make -* Cross-Compiler + binutils: gcc build for freestanding target i386-elf. If a prefix is needed, set the corresponding variable in the makefile. +* GCC 7 (or higher) Cross Compiler + matching binutils, tailored for freestanding i686-elf-targets * Doxygen: If you want to build the documentation ## Make commands
M
kernel/os_interrupts.c
→
kernel/os_interrupts.c
@@ -0,0 +1,72 @@
+#include "os_interrupts.h" +#include "os_text.h" + +#define HARDWARE_INTERRUPT (0b10001110) +#define SYSCALL_INTERRUPT (0b11101110) + +#define array_sizeof(array) (sizeof(array)/sizeof(array[0])) + +#define MAKE_IDT_ENTRY(func, selector, type) { \ + (uint16_t)(func), \ + (uint16_t)(selector), \ + 0, \ + (uint8_t)(type), \ + (uint16_t)(0xC000) \ + } + +struct interrupt_frame { + +}; + +__attribute__((interrupt)) void default_isr(struct interrupt_frame *frame) { + write("interrupt was issued\n"); +} + +__attribute__((interrupt)) void breakpoint_isr(struct interrupt_frame *frame) { + write("BREAKPOINT WAS HIT\n"); + // dump registers to stdout +} + +__attribute__((interrupt)) void double_fault_isr(struct interrupt_frame *frame) { + write("CRITICAL: DOUBLE FAULT\n"); + while (1) {} +} + +IDT_ENTRY IDT[31]; + +void install_interrupt(int index, void* func, uint16_t selector, uint8_t type) { + IDT[index].offset_0 = (uint16_t)((uint32_t)func); + IDT[index].selector = selector; + IDT[index].__zero = 0; + IDT[index].type_attr = type; + IDT[index].offset_16 = (uint16_t)((uint32_t)(func) >> 16); + //if (index == 7) { while(1) {} } +} + +struct { + uint16_t limit; + void* offset; +}__attribute__((packed)) IDT_DESC = { + sizeof(IDT), + IDT +}; + +void init_interrupts(void) { + for (uint32_t i = 0; i < array_sizeof(IDT); i++) { + switch (i) { + case 0x03: + install_interrupt(i, breakpoint_isr, 0x08, HARDWARE_INTERRUPT); + case 0x08: + install_interrupt(i, double_fault_isr, 0x08, HARDWARE_INTERRUPT); + break; + default: + install_interrupt(i, default_isr, 0x08, HARDWARE_INTERRUPT); + } + } + + __asm__ volatile ( + "lidt (%0)\n" + "sti" : : + "m" (IDT_DESC) + ); +}
M
kernel/os_interrupts.h
→
kernel/os_interrupts.h
@@ -1,4 +1,23 @@
/*! \file * Sets up the interrupt descriptor table and provides functions to * hook functions to interrupts. - */+ */ +#ifndef OS_INTERRUPTS_H +#define OS_INTERRUPTS_H + + #include <stdint.h> + +/*! + * Represents a single entry of the IDT. + */ +typedef struct { + uint16_t offset_0; + uint16_t selector; + uint8_t __zero; + uint8_t type_attr; + uint16_t offset_16; +}__attribute__((packed)) IDT_ENTRY; + +void init_interrupts(void); + +#endif
M
kernel/os_main.c
→
kernel/os_main.c
@@ -1,6 +1,9 @@
#include "os_text.h" +#include "os_interrupts.h" int main(void) { + init_interrupts(); + const char* string[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; clear(); for (int i = 0; i < 50; i++) {
M
link.txt
→
link.txt
@@ -1,5 +1,5 @@
-OUTPUT_FORMAT(binary) OUTPUT_ARCH(i386) +OUTPUT_FORMAT(elf32-i386) PAGE_SIZE = 1 << 12;@@ -29,12 +29,18 @@
KERNEL : AT(LOADADDR(SECOND_STAGE) + SIZEOF(SECOND_STAGE)) { */kernel.o(.*) + */kernel.o(.bss) } >KERNEL APPLICATION : AT(LOADADDR(KERNEL) + SIZEOF(KERNEL)) { + + } >APPLICATION - } >APPLICATION + .bss : AT(LOADADDR(APPLICATION) + SIZEOF(APPLICATION)) + { + + } >KERNEL } __SS_LMA = LOADADDR(SECOND_STAGE);
M
makefile
→
makefile
@@ -4,14 +4,14 @@ export CURRENT_DIR = $(shell pwd)
export INCLUDE_DIR = $(CURRENT_DIR)/include export DEBUG_DIR = $(CURRENT_DIR)/debug -export GCC_PREFIX = $(HOME)/opt/cross/i686-elf-/bin/i686-elf- +export GCC_PREFIX = $(HOME)/opt/cross/bin/i686-elf- ifdef DEBUG GLOBAL_BUILD = $(CURRENT_DIR)/build/debug -GCC_OPTIONS = -D DEBUG -O0 -Wno-write-strings -Qn -Wall -Wextra -fno-exceptions -nostdlib -nostartfiles -ffreestanding +GCC_OPTIONS = -D DEBUG -g -O0 -Wno-write-strings -Qn -Wall -Wextra -fno-exceptions -nostdlib -nostartfiles -ffreestanding -mgeneral-regs-only else GLOBAL_BUILD = $(CURRENT_DIR)/build/release -GCC_OPTIONS = -O1 -Wno-write-strings -Qn -Wall -Wextra -fno-exceptions -nostdlib -nostartfiles -ffreestanding +GCC_OPTIONS = -O1 -Wno-write-strings -Qn -Wall -Wextra -fno-exceptions -nostdlib -nostartfiles -ffreestanding -mgeneral-regs-only endif export GLOBAL_BUILD@@ -26,8 +26,9 @@ > @mkdir $(GLOBAL_BUILD)/kernel 2> /dev/null; true
> $(MAKE) LOCAL_BUILD=$(GLOBAL_BUILD)/boot -C boot build > $(MAKE) LOCAL_BUILD=$(GLOBAL_BUILD)/second_stage -C second_stage build > $(MAKE) LOCAL_BUILD=$(GLOBAL_BUILD)/kernel -C kernel build -> $(GCC_PREFIX)ld $(wildcard $(GLOBAL_BUILD)/*.o) -T link.txt -Map=$(DEBUG_DIR)/mapfile.txt -o $(GLOBAL_BUILD)/base.img --oformat binary -> @cp $(GLOBAL_BUILD)/base.img $(CURRENT_DIR)/build 2> /dev/null; true +> $(GCC_PREFIX)ld $(wildcard $(GLOBAL_BUILD)/*.o) -T link.txt -Map=$(DEBUG_DIR)/mapfile.txt -o build/base.o +> $(GCC_PREFIX)objcopy --only-keep-debug build/base.o $(DEBUG_DIR)/base.sym +> $(GCC_PREFIX)objcopy -O binary build/base.o build/base.img .PHONY: clear clear: