diff --git a/Makefile b/Makefile index 6cd758c..3e8a13a 100644 --- a/Makefile +++ b/Makefile @@ -37,11 +37,11 @@ obj/%.o: src/%.asm run: clean bin/shade.iso - qemu-system-x86_64 -hdd bin/shade.iso + qemu-system-x86_64 -hdd bin/shade.iso -d int -no-reboot debug: clean bin/shade.iso bin/shade.bin - qemu-system-x86_64 -s -S -hdd bin/shade.iso & - ${GDB} os-image.bin -ex "symbol-file bin/shade.bin" -ex "target remote localhost:1234" + qemu-system-x86_64 -s -S -hdd bin/shade.iso -d int -no-reboot & + ${GDB} os-image.bin -ex "set arch i386:x86-64" -ex "symbol-file bin/shade.bin" -ex "target remote localhost:1234" clean: diff --git a/bin/shade.bin b/bin/shade.bin index b755599..bc273eb 100755 Binary files a/bin/shade.bin and b/bin/shade.bin differ diff --git a/bin/shade.iso b/bin/shade.iso index 080a0ab..f81d3d4 100644 Binary files a/bin/shade.iso and b/bin/shade.iso differ diff --git a/bin/shade.iso.lock b/bin/shade.iso.lock new file mode 100644 index 0000000..e69de29 diff --git a/bochsrc.txt b/bochsrc.txt new file mode 100644 index 0000000..2ba3db3 --- /dev/null +++ b/bochsrc.txt @@ -0,0 +1,57 @@ +# configuration file generated by Bochs +plugin_ctrl: unmapped=true, biosdev=true, speaker=true, extfpuirq=true, parallel=true, serial=true, iodebug=true, pcidev=false, usb_uhci=false +config_interface: textconfig +display_library: x +memory: host=32, guest=32 +romimage: file="/usr/share/bochs/BIOS-bochs-latest", address=0x00000000, options=none +vgaromimage: file="/usr/share/bochs/VGABIOS-lgpl-latest" +boot: floppy +floppy_bootsig_check: disabled=0 +floppya: type=1_44 +# no floppyb +ata0: enabled=true, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 +ata0-master: type=disk, path="bin/shade.iso", mode=flat, cylinders=0, heads=0, spt=0, sect_size=512, model="Generic 1234", biosdetect=auto, translation=auto +ata0-slave: type=none +ata1: enabled=true, ioaddr1=0x170, ioaddr2=0x370, irq=15 +ata1-master: type=none +ata1-slave: type=none +ata2: enabled=false +ata3: enabled=false +optromimage1: file=none +optromimage2: file=none +optromimage3: file=none +optromimage4: file=none +optramimage1: file=none +optramimage2: file=none +optramimage3: file=none +optramimage4: file=none +pci: enabled=1, chipset=i440fx, slot1=none, slot2=none, slot3=none, slot4=none, slot5=none +vga: extension=vbe, update_freq=5, realtime=1, ddc=builtin +cpu: count=1:1:1, ips=4000000, quantum=16, model=bx_generic, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0 +cpuid: level=6, stepping=3, model=3, family=6, vendor_string="AuthenticAMD", brand_string="AMD Athlon(tm) processor" +cpuid: mmx=true, apic=xapic, simd=sse2, sse4a=false, misaligned_sse=false, sep=true +cpuid: movbe=false, adx=false, aes=false, sha=false, xsave=false, xsaveopt=false, avx_f16c=false +cpuid: avx_fma=false, bmi=0, xop=false, fma4=false, tbm=false, x86_64=true, 1g_pages=false +cpuid: pcid=false, fsgsbase=false, smep=false, smap=false, mwait=true +print_timestamps: enabled=0 +debugger_log: - +magic_break: enabled=0 +port_e9_hack: enabled=0 +private_colormap: enabled=0 +clock: sync=none, time0=local, rtc_sync=0 +# no cmosimage +log: - +logprefix: %t%e%d +debug: action=ignore +info: action=report +error: action=report +panic: action=ask +keyboard: type=mf, serial_delay=250, paste_delay=100000, user_shortcut=none +mouse: type=ps2, enabled=false, toggle=ctrl+mbutton +speaker: enabled=true, mode=system +parport1: enabled=true, file=none +parport2: enabled=false +com1: enabled=true, mode=null +com2: enabled=false +com3: enabled=false +com4: enabled=false diff --git a/obj/boot.o b/obj/boot.o index 8b05e99..b5ff9cd 100644 Binary files a/obj/boot.o and b/obj/boot.o differ diff --git a/obj/kernel/kernel.o b/obj/kernel/kernel.o index 0c6d63b..4c95461 100644 Binary files a/obj/kernel/kernel.o and b/obj/kernel/kernel.o differ diff --git a/obj/kernel/platform/interrupts/int.o b/obj/kernel/platform/interrupts/int.o new file mode 100644 index 0000000..0a99241 Binary files /dev/null and b/obj/kernel/platform/interrupts/int.o differ diff --git a/obj/kernel/platform/interrupts/int_lowlevel.o b/obj/kernel/platform/interrupts/int_lowlevel.o new file mode 100644 index 0000000..98f9819 Binary files /dev/null and b/obj/kernel/platform/interrupts/int_lowlevel.o differ diff --git a/old/src/boot/protected/gdt.asm b/old/src/boot/protected/gdt.asm index db35b41..df7bfe2 100644 --- a/old/src/boot/protected/gdt.asm +++ b/old/src/boot/protected/gdt.asm @@ -1,3 +1,4 @@ + gdt_start: ; use labels to compute sizes and jumps ; gdt starts with 8 byte null dd 0x0 diff --git a/old/src/kernel/platform/gdt.h b/old/src/kernel/platform/gdt.h new file mode 100644 index 0000000..5545747 --- /dev/null +++ b/old/src/kernel/platform/gdt.h @@ -0,0 +1,28 @@ +#ifndef GDT_H +#define GDT_H + +#include + +// the GDT descriptor format makes literally no sense, who came up with this +typedef struct { + uint16_t limit_low16; // Low 16 bits of limit + uint16_t base_low16; // Low 16 bits of base + uint8_t base_mid8; // Middle 8 bits of base + uint8_t access; // 7: present, 6-5: priv level, 4: type, 3: executable, 2: dc, 1: rw, 0: accessed (zero) + uint8_t limit_flags; // High 4 bits of limit AND flags (?? why). flags: 3: granularity, 2: size, 1: long, 0: reserved + uint8_t base_high8; // High 8 bits of base +} __attribute__((packed)) gdt_entry_t; + +typedef struct { + uint16_t size; // GDT size (bytes) - 1 + uint32_t offset; // Address of element 0 of the GDT +} __attribute__((packed)) gdt_ptr_t; + +static gdt_entry_t gdt[8192]; +static gdt_ptr_t gdtr; + +void init_gdt(); +void gdt_set_segment(int limit, int base, int access); +void load_gdt(); + +#endif \ No newline at end of file diff --git a/src/boot.asm b/src/boot.asm index a265974..c4eac95 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -18,6 +18,8 @@ stack_bottom: resb 16384 stack_top: +%include "src/gdt.asm" + ; _start = entry to kernel ; Since the bootloader will be gone, it doesn't make sense to return from this section .text @@ -27,6 +29,18 @@ _start: ; 32bit protected mode, no int, no paging mov esp, stack_top ; Initialize stack + cli ; Disable interrupts + lgdt [gdt_descriptor] ; load the GDT + jmp CODE_SEG:.reload_seg ; far jump into a different segment + +.reload_seg: ; now in 32bit + mov ax, DATA_SEG ; update segment registers + mov ds, ax + mov ss, ax + mov es, ax + mov fs, ax + mov gs, ax + extern kmain call kmain diff --git a/src/gdt.asm b/src/gdt.asm new file mode 100644 index 0000000..94a1299 --- /dev/null +++ b/src/gdt.asm @@ -0,0 +1,33 @@ +section .data + +gdt_start: ; use labels to compute sizes and jumps + ; gdt starts with 8 byte null + dd 0x0 + dd 0x0 + +; GDT for code segment, base = 0x00000000, length = 0xfffff +gdt_code: + dw 0xffff ; segment length + dw 0x0 ; segment base + db 0x0 ; segment base + db 10011010b ; flags + db 11001111b ; flags + segment length + db 0x0 ; segment base + +; GDT for data segment +gdt_data: + dw 0xffff ; segment length + dw 0x0 ; segment base + db 0x0 ; segment base + db 10010010b ; flags + db 11001111b ; flags + segment length + db 0x0 ; segment base + +gdt_end: + +gdt_descriptor: + dw gdt_end - gdt_start - 1 ; size, always 1 less than what it actually is + dd gdt_start ; address + +CODE_SEG equ gdt_code - gdt_start +DATA_SEG equ gdt_data - gdt_start \ No newline at end of file diff --git a/src/iso/grub.cfg b/src/iso/grub.cfg index d6d553e..1fdb214 100644 --- a/src/iso/grub.cfg +++ b/src/iso/grub.cfg @@ -1,3 +1,6 @@ +set timeout=0 +set default=0 + menuentry "shadeOS Dev Build" { multiboot /boot/shade.bin } \ No newline at end of file diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index 33df331..3002fb1 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -1,7 +1,6 @@ #include "./platform/drivers/ports.h" #include "print.h" -#include "./platform/types.h" -//#include "./platform/interrupts/int.h" +#include "./platform/interrupts/int.h" void dummy_test_entrypoint() {} @@ -46,10 +45,10 @@ void kmain() { print_str("Copyright (c) e3team 2022. All rights reserved.\n"); print_str("This program is provided \"as-is\" and no express or implied warranty is provided.\n"); print_str("The full license can be found at /sys/LICENCE on this system or ./LICENCE in the source tree.\n"); -/* + idt_init(); - kernel_msg_ok("Interrupts initialized"); __asm__ __volatile__("int $2"); -*/ + + //kernel_msg_ok("Interrupts working"); } \ No newline at end of file diff --git a/src/kernel/platform/interrupts/int.c b/src/kernel/platform/interrupts/int.c new file mode 100644 index 0000000..7474267 --- /dev/null +++ b/src/kernel/platform/interrupts/int.c @@ -0,0 +1,35 @@ +#include "int.h" +#include "../../print.h" + +#include +#include +#include + +int count = 0; + +void exception_handler() { + print_str("I"); +} + +void idt_set_descriptor(uint8_t vector, void* isr, uint8_t flags) { + idt_entry_t* descriptor = &idt[vector]; + + descriptor->isr_low = (uint32_t)isr & 0xFFFF; + descriptor->kernel_cs = 0x08; // this value can be whatever offset your kernel code selector is in your GDT + descriptor->attributes = flags; + descriptor->isr_high = (uint32_t)isr >> 16; + descriptor->reserved = 0; +} + +void idt_init() { + idtr.base = (uint32_t)&idt[0]; + idtr.limit = (uint16_t)sizeof(idt_entry_t) * 256 - 1; + + for (uint8_t vector = 0; vector < 32; vector++) { + idt_set_descriptor(vector, isr_stub_table[vector], 0x8E); + isr_stub_table[vector] = true; + } + + __asm__ volatile ("lidt %0" : : "m"(idtr)); // load the new IDT + __asm__ volatile ("sti"); // set the interrupt flag +} \ No newline at end of file diff --git a/src/kernel/platform/interrupts/int.h b/src/kernel/platform/interrupts/int.h new file mode 100644 index 0000000..f2a0d01 --- /dev/null +++ b/src/kernel/platform/interrupts/int.h @@ -0,0 +1,43 @@ +#ifndef INT_H +#define INT_H + +#include "../../util.h" +#include +#include +#include + +typedef struct { + uint16_t isr_low; // The lower 16 bits of the ISR's address + uint16_t kernel_cs; // The GDT segment selector that the CPU will load into CS before calling the ISR + uint8_t reserved; // Set to zero + uint8_t attributes; // Type and attributes; see the IDT page + uint16_t isr_high; // The higher 16 bits of the ISR's address +} __attribute__((packed)) idt_entry_t; + +__attribute__((aligned(0x10))) +static idt_entry_t idt[256]; // Create an array of IDT entries; aligned for performance + +typedef struct { + uint16_t limit; + uint32_t base; +} __attribute__((packed)) idtr_t; + +static idtr_t idtr; + +typedef struct { + uint32_t ds; /* Data segment selector */ + uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; /* Pushed by pusha. */ + 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 */ +} registers_t; + +__attribute__((noreturn)) +void exception_handler(); + +void idt_set_descriptor(uint8_t vector, void* isr, uint8_t flags); + +extern void* isr_stub_table[]; + +void idt_init(void); + +#endif \ No newline at end of file diff --git a/src/kernel/platform/interrupts/int_lowlevel.asm b/src/kernel/platform/interrupts/int_lowlevel.asm new file mode 100644 index 0000000..a030f48 --- /dev/null +++ b/src/kernel/platform/interrupts/int_lowlevel.asm @@ -0,0 +1,101 @@ +%macro isr_err_stub 1 +isr_stub_%+%1: + ;push byte %1 ; Push interrupt no to stack + + ; 1. Save CPU state + ;pusha ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax + ;mov ax, ds ; Lower 16-bits of eax = ds. + ;push eax ; save the data segment descriptor + ;mov ax, 0x10 ; kernel data segment descriptor + ;mov ds, ax + ;mov es, ax + ;mov fs, ax + ;mov gs, ax + + ; 2. Call C handler + call exception_handler + + ; 3. Restore state + ;pop eax + ;mov ds, ax + ;mov es, ax + ;mov fs, ax + ;mov gs, ax + ;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 +%endmacro +; if writing for 64-bit, use iretq instead +%macro isr_no_err_stub 1 +isr_stub_%+%1: + ;push byte 0 ; No error occured + ;push byte %1 ; Push interrupt no to stack + + ; 1. Save CPU state + ;pusha ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax + ;mov ax, ds ; Lower 16-bits of eax = ds. + ;push eax ; save the data segment descriptor + ;mov ax, 0x10 ; kernel data segment descriptor + ;mov ds, ax + ;mov es, ax + ;mov fs, ax + ;mov gs, ax + + ; 2. Call C handler + call exception_handler + + ; 3. Restore state + ;pop eax + ;mov ds, ax + ;mov es, ax + ;mov fs, ax + ;mov gs, ax + ;popa + ;add esp, 8 ; Cleans up the pushed error code and pushed ISR number + ;sti + iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP +%endmacro + +extern exception_handler + +isr_no_err_stub 0 +isr_no_err_stub 1 +isr_no_err_stub 2 +isr_no_err_stub 3 +isr_no_err_stub 4 +isr_no_err_stub 5 +isr_no_err_stub 6 +isr_no_err_stub 7 +isr_err_stub 8 +isr_no_err_stub 9 +isr_err_stub 10 +isr_err_stub 11 +isr_err_stub 12 +isr_err_stub 13 +isr_err_stub 14 +isr_no_err_stub 15 +isr_no_err_stub 16 +isr_err_stub 17 +isr_no_err_stub 18 +isr_no_err_stub 19 +isr_no_err_stub 20 +isr_no_err_stub 21 +isr_no_err_stub 22 +isr_no_err_stub 23 +isr_no_err_stub 24 +isr_no_err_stub 25 +isr_no_err_stub 26 +isr_no_err_stub 27 +isr_no_err_stub 28 +isr_no_err_stub 29 +isr_err_stub 30 +isr_no_err_stub 31 + +global isr_stub_table +isr_stub_table: +%assign i 0 +%rep 32 + dd isr_stub_%+i ; use DQ instead if targeting 64-bit +%assign i i+1 +%endrep + diff --git a/src/kernel/platform/types.h b/src/kernel/platform/types.h deleted file mode 100644 index e18f414..0000000 --- a/src/kernel/platform/types.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef TYPES_H -#define TYPES_H - -typedef unsigned int u32; -typedef int i32; -typedef unsigned short u16; -typedef short i16; -typedef unsigned char u8; -typedef char i8; - -#define high16(i32) (i32 & 0xffff) -#define low16(i32) ((i32>>16) & 0xffff) - -#define TRUE 1 -#define FALSE 0 -#define NULL 0 - -#endif \ No newline at end of file diff --git a/src/kernel/strings.c b/src/kernel/strings.c index 79897f8..eef8e40 100644 --- a/src/kernel/strings.c +++ b/src/kernel/strings.c @@ -1,5 +1,5 @@ #include "strings.h" -#include "./platform/types.h" +#include void itoa(int n, char str[]) { int i, sign;