From 17a18e4f91022ccd681575c7213677b5be38d1fe Mon Sep 17 00:00:00 2001 From: John Date: Wed, 18 Jan 2023 10:59:09 +0100 Subject: [PATCH] [Stage1] Start IDT implementation [Stage1] Screen.h improvements --- mbr/mbr.asm | 2 +- stage1/CMakeLists.txt | 5 ++-- stage1/include/interrupts.h | 43 ++++++++++++++++++++++++++++ stage1/include/screen.h | 5 +++- stage1/interrupt_utils.asm | 37 ++++++++++++++++++++++++ stage1/interrupts.c | 56 +++++++++++++++++++++++++++++++++++++ stage1/screen.c | 44 +++++++++++++++++++++++++++++ stage1/stage1.c | 13 +++++---- 8 files changed, 195 insertions(+), 10 deletions(-) create mode 100644 stage1/include/interrupts.h create mode 100644 stage1/interrupt_utils.asm create mode 100644 stage1/interrupts.c diff --git a/mbr/mbr.asm b/mbr/mbr.asm index d1631cb..05a2568 100644 --- a/mbr/mbr.asm +++ b/mbr/mbr.asm @@ -252,7 +252,7 @@ init_32: MOV FS, AX ; ^^^^ MOV GS, AX ; ^^^^ MOV SS, AX ; ^^^^ - MOV EAX, 0x7CFE ; reset stack + MOV EAX, 0x7bFF ; reset stack MOV ESP, EAX ; ^^^^ JMP 0x10000 ; jump to stage1 bootloader diff --git a/stage1/CMakeLists.txt b/stage1/CMakeLists.txt index f780ac4..3bc195c 100644 --- a/stage1/CMakeLists.txt +++ b/stage1/CMakeLists.txt @@ -1,5 +1,6 @@ -add_executable(stage1 stage1.c screen.c) -target_compile_options(stage1 PUBLIC -ffreestanding) +add_executable(stage1 stage1.c screen.c include/interrupts.h interrupts.c interrupt_utils.asm) +target_compile_options(stage1 PUBLIC "$<$:-ffreestanding>") set_target_properties(stage1 PROPERTIES LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld) target_link_options(stage1 PRIVATE -T${CMAKE_CURRENT_SOURCE_DIR}/linker.ld) +target_include_directories(stage1 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../os3_common/) target_link_libraries(stage1 libfat) \ No newline at end of file diff --git a/stage1/include/interrupts.h b/stage1/include/interrupts.h new file mode 100644 index 0000000..636c5ab --- /dev/null +++ b/stage1/include/interrupts.h @@ -0,0 +1,43 @@ +#ifndef OS3_INTERRUPTS_H +#define OS3_INTERRUPTS_H + +#include "datatypes.h" +#include "packing.h" +#include "screen.h" + +OS_PACK_START +typedef struct __idt_attributes { + os_u8 gate_type: 4; + os_u8 empty : 1; + os_u8 dpl : 2; + os_u8 present: 1; +} OS_PACK_MID idt_attributes; +OS_PACK_END + +#define IDT_GATE_TYPE_TASK 0x5 +#define IDT_GATE_TYPE_INTERRUPT_16 0x6 +#define IDT_GATE_TYPE_TRAP_16 0x7 +#define IDT_GATE_TYPE_INTERRUPT_32 0xE +#define IDT_GATE_TYPE_TRAP_32 0xF + +OS_PACK_START +typedef struct __idt_entry { + os_u16 isr_low; + os_u16 kernel_gdt_code_segment; + os_u8 reserved; + //idt_attributes attributes; + os_u8 attributes; + os_u16 isr_high; +} OS_PACK_MID idt_entry; +OS_PACK_END + +OS_PACK_START +typedef struct __idt_ptr { + os_u16 limit; + os_u32 base; +} OS_PACK_MID idt_ptr; +OS_PACK_END + +extern void fill_idt(); + +#endif //OS3_INTERRUPTS_H diff --git a/stage1/include/screen.h b/stage1/include/screen.h index 09edd43..4cc34bb 100644 --- a/stage1/include/screen.h +++ b/stage1/include/screen.h @@ -1,7 +1,10 @@ #ifndef __OS3_ST1_SCREEN_H #define __OS3_ST1_SCREEN_H -extern void write_string(const char*, int); +#include "datatypes.h" +extern void write_string(const char*, int); +extern void clear_screen(); +extern void write_number(os_u32 number); #endif \ No newline at end of file diff --git a/stage1/interrupt_utils.asm b/stage1/interrupt_utils.asm new file mode 100644 index 0000000..fd70a5a --- /dev/null +++ b/stage1/interrupt_utils.asm @@ -0,0 +1,37 @@ +; list of 256 void* to call when the corresponding interrupt is received +extern interrupt_service_list, generic_exception + +%macro interrupt_service_routine 1 +isr_stub_%+%1: + ;CALL interrupt_service_list + (%1*4) + CALL generic_exception + IRET +%endmacro + +; Generate entry points for interrupt service routines +%assign i 0 +%rep 256 +interrupt_service_routine i +%assign i i+1 +%endrep + +; list of ISR entries +global interrupt_service_table +interrupt_service_table: +%assign i 0 +%rep 256 + dd isr_stub_%+i +%assign i i+1 +%endrep + +; void load_idt(void* idt_ptr) +global load_idt +load_idt: + LIDT [ESP+4] ; load idt with SP+4 + RET ; return + +; void enable_interrupts() +global enable_interrupts +enable_interrupts: + STI ; enable interrupts + RET ; return \ No newline at end of file diff --git a/stage1/interrupts.c b/stage1/interrupts.c new file mode 100644 index 0000000..2570961 --- /dev/null +++ b/stage1/interrupts.c @@ -0,0 +1,56 @@ +#include "include/interrupts.h" + +#define EFFECTIVE_INTERRUPT_AMOUNT 32 + +__attribute__((aligned(0x10))) +idt_entry main_idt[EFFECTIVE_INTERRUPT_AMOUNT]; +idt_ptr main_idt_ptr; +volatile void* interrupt_service_list[EFFECTIVE_INTERRUPT_AMOUNT]; + +void generic_exception() { + //clear_screen(); + write_string("Exception received: ", 0); + write_number(0); + write_string("\n", 0); + __asm__("cli; hlt;"); + while(1) { + + } +} + +/* The following is defined in interrupt_utils.asm */ +extern void* interrupt_service_table[]; +extern void load_idt(void* idtr_ptr); +extern void enable_interrupts(); +/* --- */ + +void fill_idt() { + + main_idt_ptr.base = (os_u32) &main_idt[0]; + main_idt_ptr.limit = ((os_u16) (sizeof(idt_entry) * EFFECTIVE_INTERRUPT_AMOUNT)) - 1; + os_u32 val = (os_u32) interrupt_service_table[0]; + write_string("ISR address: ", 0); + write_number(val); + write_string("\n", 1); + for (int i = 0; i < EFFECTIVE_INTERRUPT_AMOUNT; i++) { + + //os_u32 val = (os_u32) interrupt_service_table[0]; + os_u32 val = (os_u32) &generic_exception; + main_idt[i].isr_low = (os_u16)(val & 0xFFFF); + main_idt[i].isr_high = (os_u16)(val >> 16); + main_idt[i].kernel_gdt_code_segment = 0x08; + main_idt[i].reserved = 0; + /* + main_idt[i].attributes.present = 1; + main_idt[i].attributes.gate_type = IDT_GATE_TYPE_INTERRUPT_32; + main_idt[i].attributes.empty = 0; + main_idt[i].attributes.dpl = i == 0x49 ? 3 : 0; + */ + main_idt[i].attributes = 0x8e; + + interrupt_service_list[i] = (void*)&generic_exception; + } + + load_idt((void*)&main_idt_ptr); + enable_interrupts(); +} \ No newline at end of file diff --git a/stage1/screen.c b/stage1/screen.c index 718e404..9ecdc32 100644 --- a/stage1/screen.c +++ b/stage1/screen.c @@ -21,6 +21,9 @@ void write_string(const char* str, int max_len) { } if (c == '\n') { + if (y == 24) { + clear_screen(); + } y = (y + 1) % 25; x = 0; str++; @@ -30,6 +33,9 @@ void write_string(const char* str, int max_len) { write_character(c); x++; if (x >= 80) { + if (y == 24) { + clear_screen(); + } y = (y + 1) % 25; x = 0; } @@ -37,3 +43,41 @@ void write_string(const char* str, int max_len) { i++; } while(i < max_len || max_len == 0); } + +void clear_screen() { + os_u16* ptr = (os_u16*) 0xB8000; + for (int y = 0; y < 25; y++) { + for (int x = 0; x < 80; x++) { + *ptr = 0; + ptr++; + } + } + x = 0; + y = 0; +} + +void write_number(os_u32 number) { + char buffer[32]; + char buffer_2[32]; + + os_s32 i = 1; + while(i < 32) { + if (i > 1 && number == 0) { + break; + } + + buffer[i] = ((char)(number % 10)) + '0'; + i++; + number /= 10; + } + i--; + buffer[0] = '\0'; + char* buffer_2_ptr = buffer_2; + while(i >= 0) { + *buffer_2_ptr = buffer[i]; + buffer_2_ptr++; + i--; + } + + write_string(buffer_2, 0); +} \ No newline at end of file diff --git a/stage1/stage1.c b/stage1/stage1.c index 56089d2..ecf598d 100644 --- a/stage1/stage1.c +++ b/stage1/stage1.c @@ -1,16 +1,17 @@ -// -// Created by barba on 06/10/2022. -// - #include "../os3_common/datatypes.h" #include "../os3_common/packing.h" #include "include/screen.h" +#include "include/interrupts.h" int main() { + clear_screen(); write_string("OS3 Booted into stage 1!\n", 0); - write_string("Looking for stage 2....", 0); + write_string("Looking for stage 2....\n", 0); + fill_idt(); + os_u32 i = 0; while(1) { - + write_number(i++); + write_string("\n", 0); }; return 0;