diff --git a/kernel/arch/i386/boot/boot.S b/kernel/arch/i386/boot/boot.S index 08389cc..62eaca6 100644 --- a/kernel/arch/i386/boot/boot.S +++ b/kernel/arch/i386/boot/boot.S @@ -24,10 +24,12 @@ stack_top: .global _start .type _start, @function _start: - movl $stack_top, %esp cli call gdt_init # initialize the GDT + movl $stack_top, %esp + call terminal_initialize call idt_init # initialize the IDT + call PIC_remap call kernel_main # transfer control to main kernel # Hang if kernel_main unexpectedly returns 1: hlt diff --git a/kernel/arch/i386/boot/gdt.c b/kernel/arch/i386/boot/gdt.c index 01588f7..7b8ee61 100644 --- a/kernel/arch/i386/boot/gdt.c +++ b/kernel/arch/i386/boot/gdt.c @@ -41,8 +41,18 @@ void gdt_init(void) { gdt_fill(GDT+i, rows+i); } - gp.base = &GDT; - gp.limit = (GDT_ENTRIES * sizeof(gdt_entry)) - 1; + gp.base = (uintptr_t)&GDT[0]; + gp.limit = sizeof(gdt_entry) * GDT_ENTRIES - 1; - gdt_load(); + __asm__ volatile("lgdt %0" : : "m"(gp)); // Load new GDT + __asm__ volatile( + "jmp $0x0008, $fix_cs\n" + "fix_cs:\n" + "mov $0x0010, %ax\n" + "mov %ax, %ds\n" + "mov %ax, %es\n" + "mov %ax, %fs\n" + "mov %ax, %gs\n" + "mov %ax, %ss" + ); } diff --git a/kernel/arch/i386/boot/gdt_load.S b/kernel/arch/i386/boot/gdt_load.S deleted file mode 100644 index 70eac4d..0000000 --- a/kernel/arch/i386/boot/gdt_load.S +++ /dev/null @@ -1,20 +0,0 @@ -# Referenced from https://github.com/tendstofortytwo/clay -# kernel/boot/gdt.s - -.global gdt_load -.type gdt_load, @function -gdt_load: - lgdt (gp) - mov %cr0, %eax - or $0x1, %eax - mov %eax, %cr0 - jmp $0x08, $reload - -reload: - mov $0x10, %ax - mov %ax, %ds - mov %ax, %es - mov %ax, %fs - mov %ax, %gs - mov %ax, %ss - ret diff --git a/kernel/arch/i386/boot/idt.c b/kernel/arch/i386/boot/idt.c index 3f2d98f..688ecc0 100644 --- a/kernel/arch/i386/boot/idt.c +++ b/kernel/arch/i386/boot/idt.c @@ -1,49 +1,169 @@ #include #include -__attribute__((interrupt)) void hello_interrupt(idt_frame* frame) { - printf("Hello from interrupt!\n"); - printf("ip=0x%x, cs=0x%x, flags=0b%b\n", frame->ip, frame->cs, frame->flags); +__attribute__((interrupt)) void int_handler(void* frame, unsigned int number) { + unsigned int err = 0; + idt_frame* idt_ptr; + idt_frame_err* idt_ptr_e; + switch(number) { + case 8: + case 10: + case 11: + case 12: + case 13: + case 14: + case 17: + case 21: + idt_ptr_e = (idt_frame_err*)frame; + err = 1; + break; + default: + idt_ptr = (idt_frame*)frame; + break; + } + + switch(number) { + case 0: + printf("#DE Divide Error!\n"); + break; + case 1: + printf("#DB Debug Exception!\n"); + break; + case 2: + printf("NMI Interrupt!\n"); + break; + case 3: + printf("#BP Breakpoint!\n"); + break; + case 4: + printf("#OF Overflow!\n"); + break; + case 5: + printf("#BR Bound Range Exceeded!\n"); + break; + case 6: + printf("#Invalid Opcode (Undefined Opcode)!\n"); + break; + case 7: + printf("#NM Device Not Available (No Math Coprocessor)!\n"); + break; + case 9: + printf("Coprocessor Segment Overrun (reserved)!\n"); + break; + case 16: + printf("#MF x87 FPU Floating-Point Error (Math Fault)!\n"); + break; + case 18: + printf("#MC Machine Check!\n"); + break; + case 19: + printf("#XM SIMD Floating-Point Exception!\n"); + break; + case 20: + printf("#VE Virtualization Exception!\n"); + break; + //////// + case 8: + printf("#DF Double Fault!\n"); + break; + case 10: + printf("#TS Invalid TSS!\n"); + break; + case 11: + printf("#NP Segment Not Present!\n"); + break; + case 12: + printf("#SS Stack-Segment Fault!\n"); + break; + case 13: + printf("#GP General Protection!\n"); + break; + case 14: + printf("#PF Page Fault!\n"); + break; + case 17: + printf("#AC Alignment Check!\n"); + break; + case 21: + printf("#CP Control Protection Exception!\n"); + break; + } + + if(err){ + printf("err: 0x%X, ip: 0x%X, cs: 0x%X, flags: 0x%X, sp: 0x%X, ss: 0x%X\n", + idt_ptr_e->err, idt_ptr_e->ip, idt_ptr_e->cs, idt_ptr_e->flags, idt_ptr_e->sp, idt_ptr_e->ss); + } else { + printf("ip: 0x%X, cs: 0x%X, flags: 0x%X, sp: 0x%X, ss: 0x%X\n", + idt_ptr->ip, idt_ptr->cs, idt_ptr->flags, idt_ptr->sp, idt_ptr->ss); + } + return; } -__attribute__((interrupt)) void hello_interrupt_err(idt_frame_err* frame) { - printf("Hello from error interrupt!\n"); - printf("ip=0x%x, cs=0x%x, flags=0b%b, err=0x%x\n", frame->ip, frame->cs, frame->flags, frame->err); - asm volatile("cli; hlt"); +#define INT_WRAPPER(NUM) __attribute__((interrupt)) void int##NUM##_wrapper(void* frame) { \ + int_handler(frame, NUM); \ } -void idt_fill_row(idt_entry_t* target, idt* source) { - target->isr_low = source->offset & 0xFFFF; - target->isr_high = (source->offset >> 16) & 0xFFFF; - target->kernel_cs = source->segment; - target->flags = 0x80; - target->flags |= (source->ring & 0x3) << 5; - target->flags |= (source->gate & 0xF); - target->reserved = 0; -} +INT_WRAPPER(0) +INT_WRAPPER(1) +INT_WRAPPER(2) +INT_WRAPPER(3) +INT_WRAPPER(4) +INT_WRAPPER(5) +INT_WRAPPER(6) +INT_WRAPPER(7) +INT_WRAPPER(8) +INT_WRAPPER(9) +INT_WRAPPER(10) +INT_WRAPPER(11) +INT_WRAPPER(12) +INT_WRAPPER(13) +INT_WRAPPER(14) +INT_WRAPPER(16) +INT_WRAPPER(17) +INT_WRAPPER(18) +INT_WRAPPER(19) +INT_WRAPPER(20) +INT_WRAPPER(21) -__attribute__((aligned(0x10))) idt_entry_t IDT[IDT_ROWS]; -idtr_t idtptr; +static __attribute__((aligned(0x10))) idt_entry_t idt[IDT_MAX_DESCRIPTORS]; +static idtr_t idtptr; + +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; // Whatever offset kernel code selector is in GDT + descriptor->flags = flags; + descriptor->isr_high = (uint32_t)isr >> 16; + descriptor->reserved = 0; +} void idt_init(void) { - idt rows[] = { - {(uint32_t)hello_interrupt, 0x08, INT_GATE32, 0}, - {(uint32_t)hello_interrupt_err, 0x08, INT_GATE32, 0}, - }; + idtptr.base = (uintptr_t)&idt[0]; + idtptr.limit = (uint16_t)sizeof(idt_entry_t) * IDT_MAX_DESCRIPTORS - 1; - int valid_rows = sizeof(rows) / sizeof(idt_entry_t); + idt_set_descriptor(0, int0_wrapper, 0x8E); + idt_set_descriptor(0, int0_wrapper, 0x8E); + idt_set_descriptor(1, int1_wrapper, 0x8E); + idt_set_descriptor(2, int2_wrapper, 0x8E); + idt_set_descriptor(3, int3_wrapper, 0x8E); + idt_set_descriptor(4, int4_wrapper, 0x8E); + idt_set_descriptor(5, int5_wrapper, 0x8E); + idt_set_descriptor(6, int6_wrapper, 0x8E); + idt_set_descriptor(7, int7_wrapper, 0x8E); + idt_set_descriptor(8, int8_wrapper, 0x8E); + idt_set_descriptor(9, int9_wrapper, 0x8E); + idt_set_descriptor(10, int10_wrapper, 0x8E); + idt_set_descriptor(11, int11_wrapper, 0x8E); + idt_set_descriptor(12, int12_wrapper, 0x8E); + idt_set_descriptor(13, int13_wrapper, 0x8E); + idt_set_descriptor(14, int14_wrapper, 0x8E); + idt_set_descriptor(16, int16_wrapper, 0x8E); + idt_set_descriptor(17, int17_wrapper, 0x8E); + idt_set_descriptor(18, int18_wrapper, 0x8E); + idt_set_descriptor(19, int19_wrapper, 0x8E); + idt_set_descriptor(20, int20_wrapper, 0x8E); + idt_set_descriptor(21, int21_wrapper, 0x8E); - for(int i = 0; i < valid_rows; ++i) { - idt_fill_row(IDT+i, rows+i); - } - - idt blank_row = {0, 0, 0, 0}; - for(int i = valid_rows; i < IDT_ROWS; ++i) { - idt_fill_row(IDT+i, &blank_row); - } - - idtptr.base = &IDT; - idtptr.limit = (IDT_ROWS * sizeof(idt_entry_t)) - 1; - - idt_load(); + __asm__ volatile("lidt %0" : : "m"(idtptr)); // Load new IDT + __asm__ volatile("sti"); // Set interrupt flag } \ No newline at end of file diff --git a/kernel/arch/i386/boot/idt_load.S b/kernel/arch/i386/boot/idt_load.S deleted file mode 100644 index dd62b89..0000000 --- a/kernel/arch/i386/boot/idt_load.S +++ /dev/null @@ -1,6 +0,0 @@ -.global idt_load -.type idt_load, @function -idt_load: - lidt (idtptr) - sti - ret \ No newline at end of file diff --git a/kernel/arch/i386/boot/pic.c b/kernel/arch/i386/boot/pic.c new file mode 100644 index 0000000..10ee789 --- /dev/null +++ b/kernel/arch/i386/boot/pic.c @@ -0,0 +1,30 @@ +#include + +void PIC_remap() { + unsigned char a1, a2; + + a1 = inb(PIC1_DATA); // save masks + a2 = inb(PIC2_DATA); + + outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4); // Start init sequence in cascade mode + io_wait(); + outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4); + io_wait(); + + outb(PIC1_DATA, PIC1_OFFSET); // ICW2: Master PIC vector offset + io_wait(); + outb(PIC2_DATA, PIC2_OFFSET); // ICW2: Slave PIC vector offset + io_wait(); + outb(PIC1_DATA, 4); // ICW3: tell Master PIC that theres 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); +} \ No newline at end of file diff --git a/kernel/arch/i386/make.config b/kernel/arch/i386/make.config index f97727a..c2d1037 100644 --- a/kernel/arch/i386/make.config +++ b/kernel/arch/i386/make.config @@ -7,7 +7,6 @@ KERNEL_ARCH_OBJS=\ $(ARCHDIR)/boot/boot.o \ $(ARCHDIR)/vga/tty.o \ $(ARCHDIR)/boot/gdt.o \ -$(ARCHDIR)/boot/gdt_load.o \ $(ARCHDIR)/paging/paging.o \ $(ARCHDIR)/boot/idt.o \ -$(ARCHDIR)/boot/idt_load.o \ No newline at end of file +$(ARCHDIR)/boot/pic.o \ No newline at end of file diff --git a/kernel/include/kernel/gdt.h b/kernel/include/kernel/gdt.h index a2e59d2..a1b111d 100644 --- a/kernel/include/kernel/gdt.h +++ b/kernel/include/kernel/gdt.h @@ -33,7 +33,6 @@ typedef struct { void gdt_fill(gdt_entry*, gdt*); void gdt_init(void); -extern void gdt_load(); extern uint32_t TSS[32]; extern gdt_entry GDT[GDT_ENTRIES]; diff --git a/kernel/include/kernel/idt.h b/kernel/include/kernel/idt.h index c39a840..90c88a4 100644 --- a/kernel/include/kernel/idt.h +++ b/kernel/include/kernel/idt.h @@ -3,17 +3,7 @@ #include -#define IDT_ROWS 256 -#define TASK_GATE 0x5 -#define INT_GATE16 0x6 -#define TRAP_GATE16 0x7 -#define INT_GATE32 0xE -#define TRAP_GATE32 0xF - -typedef struct { - uint16_t limit; - uint32_t base; -} __attribute__((packed)) idtr_t; +#define IDT_MAX_DESCRIPTORS 256 typedef struct { uint16_t isr_low; // lower 16-bits of ISR address @@ -24,11 +14,9 @@ typedef struct { } __attribute__((packed)) idt_entry_t; typedef struct { - uint32_t offset; - uint16_t segment; - uint8_t gate; - uint8_t ring; -} idt; + uint16_t limit; + uint32_t base; +} __attribute__((packed)) idtr_t; typedef struct { uint32_t ip; @@ -47,7 +35,6 @@ typedef struct { uint32_t ss; } __attribute__((packed)) idt_frame_err; -extern void idt_load(); -extern idtr_t idtptr; +static idtr_t idtptr; #endif \ No newline at end of file diff --git a/kernel/include/kernel/paging.h b/kernel/include/kernel/paging.h index 39df8e6..f30e004 100644 --- a/kernel/include/kernel/paging.h +++ b/kernel/include/kernel/paging.h @@ -1,7 +1,7 @@ #ifndef _KERNEL_PAGING_H #define _KERNEL_PAGING_H -extern void load_page_dir(unsigned int*); +extern void load_page_dir(uint32_t*); extern void enable_paging(); #endif \ No newline at end of file diff --git a/kernel/include/kernel/pic.h b/kernel/include/kernel/pic.h new file mode 100644 index 0000000..fb2db5f --- /dev/null +++ b/kernel/include/kernel/pic.h @@ -0,0 +1,51 @@ +#ifndef _KERNEL_PIC_H +#define _KERNEL_PIC_H + +#include + +#define PIC1 0x20 +#define PIC1_COMMAND PIC1 +#define PIC1_DATA PIC1+1 +#define PIC1_OFFSET 0x20 + +#define PIC2 0xA0 +#define PIC2_COMMAND PIC2 +#define PIC2_DATA PIC2+1 +#define PIC2_OFFSET 0x28 + +#define PIC_EOI 0x20 + +#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) EDI +#define ICW4_BUF_SLAVE 0x08 // Buffered mode/slave +#define ICW4_BUF_MASTER 0x0C // Buffered mode/master +#define ICW4_SFNM 0x10 // Special fully nested (not) + +static inline void outb(uint16_t port, uint8_t val) { + asm volatile("outb %0, %1" : : "a"(val), "Nd"(port)); +} + +static inline uint8_t inb(uint16_t port) { + uint8_t ret; + asm volatile("inb %1, %0" : "=a"(ret) : "Nd"(port)); + return ret; +} + +static inline void io_wait() { + outb(0x80, 0); +} + +static inline void pic_eoi(uint8_t irq) { + if (irq >= 8) { + outb(PIC2_COMMAND, PIC_EOI); + } + outb(PIC1_COMMAND, PIC_EOI); +} + +#endif \ No newline at end of file diff --git a/kernel/kernel/exception.c b/kernel/kernel/exception.c deleted file mode 100644 index e46be97..0000000 --- a/kernel/kernel/exception.c +++ /dev/null @@ -1,8 +0,0 @@ -#include - -__attribute__((noreturn)) -void exception_handler(void); -void exception_handler() { - printf("Kernel exception!\n"); - __asm__ volatile ("cli; hlt"); -} \ No newline at end of file diff --git a/kernel/kernel/kernel.c b/kernel/kernel/kernel.c index 3952e39..33ac05f 100644 --- a/kernel/kernel/kernel.c +++ b/kernel/kernel/kernel.c @@ -31,13 +31,11 @@ void paging_init() { void kernel_main(void) { paging_init(); - terminal_initialize(); printf("Hello, kernel World!\n"); printf("String test: %s\n", "HELLOOOOO"); printf("Float test: %.10f\n", 0.123456789); printf("Int test: %d\n", 747474); printf("Hex test: 0x%x\n", 0xDEADBEEF); printf("And now for 0.1 + 0.2...... which is: %.17f\n", 0.1 + 0.2); - asm("int $0"); - asm("cli"); + asm("cli; hlt"); } diff --git a/libc/ssp/ssp.c b/libc/ssp/ssp.c index c18c769..120e847 100644 --- a/libc/ssp/ssp.c +++ b/libc/ssp/ssp.c @@ -1,6 +1,7 @@ #include #include #include +#include #if UINT32_MAX == UINTPTR_MAX #define STACK_CHK_GUARD 0x74316974 @@ -17,4 +18,6 @@ void __stack_chk_fail(void){ #elif __is_rockos_kernel panic("Stack smashing detected!"); #endif -} + printf("Stack smashing detected!"); + for(;;); +} \ No newline at end of file diff --git a/libc/stdio/vprintf.c b/libc/stdio/vprintf.c index 2e309ae..e7cf1ee 100644 --- a/libc/stdio/vprintf.c +++ b/libc/stdio/vprintf.c @@ -190,11 +190,13 @@ int vprintf(const char* format, va_list list) { switch (specifier) { case 'X': base = 16; + // fall through case 'x': base = base == 10 ? 17 : base; if (altForm) { displayString("0x", &chars); } + // fall through case 'u': { switch (length) { @@ -383,7 +385,7 @@ int vprintf(const char* format, va_list list) { case 'e': case 'E': emode = true; - + // fall through case 'f': case 'F': case 'g':