diff --git a/OVMFbin/OVMF_VARS-pure-efi.fd b/OVMFbin/OVMF_VARS-pure-efi.fd index 453efac..4ecdf8b 100644 Binary files a/OVMFbin/OVMF_VARS-pure-efi.fd and b/OVMFbin/OVMF_VARS-pure-efi.fd differ diff --git a/kernel/bin/CustomOS.img b/kernel/bin/CustomOS.img index 2f0d7ab..1c3648f 100644 Binary files a/kernel/bin/CustomOS.img and b/kernel/bin/CustomOS.img differ diff --git a/kernel/bin/kernel.elf b/kernel/bin/kernel.elf index e334a67..cb52485 100755 Binary files a/kernel/bin/kernel.elf and b/kernel/bin/kernel.elf differ diff --git a/kernel/lib/interrupts/interrupts.o b/kernel/lib/interrupts/interrupts.o index b0e5086..d5a75c6 100644 Binary files a/kernel/lib/interrupts/interrupts.o and b/kernel/lib/interrupts/interrupts.o differ diff --git a/kernel/lib/kernel.o b/kernel/lib/kernel.o index 39b9e9a..b8a476d 100644 Binary files a/kernel/lib/kernel.o and b/kernel/lib/kernel.o differ diff --git a/kernel/lib/kernelUtil.o b/kernel/lib/kernelUtil.o index d26aeca..7f88e99 100644 Binary files a/kernel/lib/kernelUtil.o and b/kernel/lib/kernelUtil.o differ diff --git a/kernel/lib/userinput/mouse.o b/kernel/lib/userinput/mouse.o new file mode 100644 index 0000000..ea0b382 Binary files /dev/null and b/kernel/lib/userinput/mouse.o differ diff --git a/kernel/src/interrupts/interrupts.cpp b/kernel/src/interrupts/interrupts.cpp index bcf694d..9683455 100644 --- a/kernel/src/interrupts/interrupts.cpp +++ b/kernel/src/interrupts/interrupts.cpp @@ -3,22 +3,22 @@ #include "../IO.h" #include "../userinput/keyboard.h" -__attribute__((interrupt)) void PageFault_Handler(struct interrupt_frame* frame) { +__attribute__((interrupt)) void PageFault_Handler(interrupt_frame* frame) { Panic("Page Fault"); while (true); } -__attribute__((interrupt)) void DoubleFault_Handler(struct interrupt_frame* frame) { +__attribute__((interrupt)) void DoubleFault_Handler(interrupt_frame* frame) { Panic("Double Fault"); while (true); } -__attribute__((interrupt)) void GPFault_Handler(struct interrupt_frame* frame) { +__attribute__((interrupt)) void GPFault_Handler(interrupt_frame* frame) { Panic("General Protection Fault"); while (true); } -__attribute__((interrupt)) void KeyboardInterrupt_Handler(struct interrupt_frame* frame) { +__attribute__((interrupt)) void KeyboardInterrupt_Handler(interrupt_frame* frame) { uint8_t scancode = inb(0x60); HandleKeyboard(scancode); @@ -26,6 +26,14 @@ __attribute__((interrupt)) void KeyboardInterrupt_Handler(struct interrupt_frame PIC_EndMaster(); } +__attribute__((interrupt)) void MouseInterrupt_Handler(interrupt_frame* frame) { + uint8_t mouseData = inb(0x60); + + HandlePS2Mouse(mouseData); + + PIC_EndSlave(); +} + void PIC_EndMaster() { outb(PIC1_COMMAND, PIC_EOI); } diff --git a/kernel/src/interrupts/interrupts.h b/kernel/src/interrupts/interrupts.h index 5529e8c..e4d7af6 100644 --- a/kernel/src/interrupts/interrupts.h +++ b/kernel/src/interrupts/interrupts.h @@ -1,5 +1,6 @@ #pragma once #include "../BasicRenderer.h" +#include "../userinput/mouse.h" #define PIC1_COMMAND 0x20 #define PIC1_DATA 0x21 @@ -12,11 +13,12 @@ #define ICW4_8086 0x01 struct interrupt_frame; -__attribute__((interrupt)) void PageFault_Handler(struct interrupt_frame* frame); -__attribute__((interrupt)) void DoubleFault_Handler(struct interrupt_frame* frame); -__attribute__((interrupt)) void GPFault_Handler(struct interrupt_frame* frame); +__attribute__((interrupt)) void PageFault_Handler(interrupt_frame* frame); +__attribute__((interrupt)) void DoubleFault_Handler(interrupt_frame* frame); +__attribute__((interrupt)) void GPFault_Handler(interrupt_frame* frame); -__attribute__((interrupt)) void KeyboardInterrupt_Handler(struct interrupt_frame* frame); +__attribute__((interrupt)) void KeyboardInterrupt_Handler(interrupt_frame* frame); +__attribute__((interrupt)) void MouseInterrupt_Handler(interrupt_frame* frame); void RemapPIC(); void PIC_EndMaster(); diff --git a/kernel/src/kernel.cpp b/kernel/src/kernel.cpp index 2d25849..d95d1d6 100644 --- a/kernel/src/kernel.cpp +++ b/kernel/src/kernel.cpp @@ -3,12 +3,11 @@ extern "C" void _start(BootInfo* bootInfo) { KernelInfo kernelInfo = InitializeKernel(bootInfo); PageTableManager* pageTableManager = kernelInfo.pageTableManager; - - GlobalRenderer->ClearColour = 0xFF191919; - GlobalRenderer->Clear(); - GlobalRenderer->Print("Kernel initialized successfully!"); - GlobalRenderer->Next(); + while (true) { + ProcessMousePacket(); + } + // make sure we never return from our OS while (true); } \ No newline at end of file diff --git a/kernel/src/kernelUtil.cpp b/kernel/src/kernelUtil.cpp index 178db35..e40017e 100644 --- a/kernel/src/kernelUtil.cpp +++ b/kernel/src/kernelUtil.cpp @@ -45,40 +45,31 @@ void PrepareMemory(BootInfo* bootInfo){ } IDTR idtr; + +void SetIDTGate(void* handler, uint8_t entryOffset, uint8_t type_attr, uint8_t selector) { + IDTDescEntry* interrupt = (IDTDescEntry*)(idtr.Offset + entryOffset * sizeof(IDTDescEntry)); + interrupt->SetOffset((uint64_t)handler); + interrupt->type_attr = type_attr; + interrupt->selector = selector; +} + void PrepareInterrupts() { idtr.Limit = 0x0FFF; idtr.Offset = (uint64_t)GlobalAllocator.RequestPage(); memset((void*)idtr.Offset, 0, 0x1000); - IDTDescEntry* int_PageFault = (IDTDescEntry*)(idtr.Offset + 0xE * sizeof(IDTDescEntry)); - int_PageFault->SetOffset((uint64_t)PageFault_Handler); - int_PageFault->type_attr = IDT_TA_InterruptGate; - int_PageFault->selector = 0x08; // kernel code segment - - IDTDescEntry* int_DoubleFault = (IDTDescEntry*)(idtr.Offset + 0x8 * sizeof(IDTDescEntry)); - int_DoubleFault->SetOffset((uint64_t)DoubleFault_Handler); - int_DoubleFault->type_attr = IDT_TA_InterruptGate; - int_DoubleFault->selector = 0x08; // kernel code segment - - IDTDescEntry* int_GPFault = (IDTDescEntry*)(idtr.Offset + 0xD * sizeof(IDTDescEntry)); - int_GPFault->SetOffset((uint64_t)GPFault_Handler); - int_GPFault->type_attr = IDT_TA_InterruptGate; - int_GPFault->selector = 0x08; // kernel code segment - - IDTDescEntry* int_Keyboard = (IDTDescEntry*)(idtr.Offset + 0x21 * sizeof(IDTDescEntry)); - int_Keyboard->SetOffset((uint64_t)KeyboardInterrupt_Handler); - int_Keyboard->type_attr = IDT_TA_InterruptGate; - int_Keyboard->selector = 0x08; // kernel code segment + + SetIDTGate((void*)PageFault_Handler, 0xE, IDT_TA_InterruptGate, 0x08); + SetIDTGate((void*)DoubleFault_Handler, 0x8, IDT_TA_InterruptGate, 0x08); + SetIDTGate((void*)GPFault_Handler, 0xD, IDT_TA_InterruptGate, 0x08); + SetIDTGate((void*)KeyboardInterrupt_Handler, 0x21, IDT_TA_InterruptGate, 0x08); + SetIDTGate((void*)MouseInterrupt_Handler, 0x2C, IDT_TA_InterruptGate, 0x08); // load idt asm("lidt %0" : : "m" (idtr)); // remap pic so we can get hardware interrupts RemapPIC(); - outb(PIC1_DATA, 0b11111101); // unmask 2nd interrupt - outb(PIC2_DATA, 0b11111111); - - asm ("sti"); } BasicRenderer r = BasicRenderer(NULL, NULL); @@ -86,16 +77,42 @@ KernelInfo InitializeKernel(BootInfo* bootInfo){ r = BasicRenderer(bootInfo->framebuffer, bootInfo->psf1_Font); GlobalRenderer = &r; + GlobalRenderer->ClearColour = 0xFF191919; + GlobalRenderer->Clear(); + + GlobalRenderer->Print("Setting up GDT..."); + GlobalRenderer->Next(); + GDTDescriptor gdtDescriptor; gdtDescriptor.Size = sizeof(GDT) - 1; gdtDescriptor.Offset = (uint64_t)&DefaultGDT; LoadGDT(&gdtDescriptor); + GlobalRenderer->Print("Preparing memory... (this doesn't always work, you may need to restart. sorry.)"); + GlobalRenderer->Next(); + PrepareMemory(bootInfo); - memset(bootInfo->framebuffer->BaseAddress, 0, bootInfo->framebuffer->BufferSize); + //memset(bootInfo->framebuffer->BaseAddress, 0, bootInfo->framebuffer->BufferSize); + + GlobalRenderer->Print("Setting up interrupts..."); + GlobalRenderer->Next(); PrepareInterrupts(); + GlobalRenderer->Print("Setting up mouse..."); + GlobalRenderer->Next(); + InitPS2Mouse(); + + outb(PIC1_DATA, 0b11111001); // unmask 2nd interrupt + outb(PIC2_DATA, 0b11101111); + + asm ("sti"); // enable interrupts + + GlobalRenderer->Print("Init complete!"); + GlobalRenderer->Next(); + + + return kernelInfo; } \ No newline at end of file diff --git a/kernel/src/kernelUtil.h b/kernel/src/kernelUtil.h index 9beba51..9343c76 100644 --- a/kernel/src/kernelUtil.h +++ b/kernel/src/kernelUtil.h @@ -11,6 +11,7 @@ #include "paging/PageMapIndexer.h" #include "paging/paging.h" #include "paging/PageTableManager.h" +#include "userinput/mouse.h" struct BootInfo { Framebuffer* framebuffer; diff --git a/kernel/src/userinput/mouse.cpp b/kernel/src/userinput/mouse.cpp new file mode 100644 index 0000000..188acdc --- /dev/null +++ b/kernel/src/userinput/mouse.cpp @@ -0,0 +1,141 @@ +#include "mouse.h" +#include "../IO.h" + +void MouseWait() { + uint64_t timeout = 100000; + while (timeout--) { + if (inb(0x64) & 0b10 == 0) + return; + } + +} + +void MouseWaitInput() { + uint64_t timeout = 100000; + while (timeout--) { + if (inb(0x64) & 0b1) + return; + } + +} + +void MouseWrite(uint8_t value) { + MouseWait(); + outb(0x64, 0xD4); + MouseWait(); + outb(0x60, value); +} + +uint8_t MouseRead() { + MouseWaitInput(); + return inb(0x60); +} + +uint8_t mouseCycle = 0; +uint8_t mousePacket[4]; +bool mousePacketReady = false; + +Point mousePosition; + +void HandlePS2Mouse(uint8_t data) { + switch (mouseCycle) { + case 0: + if (mousePacketReady) break; + + if (data & 0b00001000 == 0) break; + + mousePacket[0] = data; + mouseCycle++; + break; + case 1: + if (mousePacketReady) break; + mousePacket[1] = data; + mouseCycle++; + break; + case 2: + if (mousePacketReady) break; + mousePacket[2] = data; + mousePacketReady = true; + mouseCycle = 0; + break; + } +} + +void ProcessMousePacket() { + if (!mousePacketReady) return; + mousePacketReady = false; + + bool xNegative, yNegative, xOverflow, yOverflow; + + if (mousePacket[0] & PS2XSign) { + xNegative = true; + } else xNegative = false; + + if (mousePacket[0] & PS2YSign) { + yNegative = true; + } else yNegative = false; + + if (mousePacket[0] & PS2XOverflow) { + xOverflow = true; + } else xOverflow = false; + + if (mousePacket[0] & PS2YOverflow) { + yOverflow = true; + } else yOverflow = false; + + if (!xNegative) { + mousePosition.x += mousePacket[1]; + if (xOverflow) { + mousePosition.x += 255; + } + } else { + mousePacket[1] = 256 - mousePacket[1]; + mousePosition.x -= mousePacket[1]; + if (xOverflow) { + mousePosition.x -= 255; + } + } + + if (!yNegative) { + mousePosition.y -= mousePacket[2]; + if (yOverflow) { + mousePosition.y -= 255; + } + } else { + mousePacket[2] = 256 - mousePacket[2]; + mousePosition.y += mousePacket[2]; + if (yOverflow) { + mousePosition.y += 255; + } + } + + if (mousePosition.x < 0) mousePosition.x = 0; + if (mousePosition.x > GlobalRenderer->targetFramebuffer->Width-1) mousePosition.x = GlobalRenderer->targetFramebuffer->Width; + if (mousePosition.y < 0) mousePosition.y = 0; + if (mousePosition.y > GlobalRenderer->targetFramebuffer->Height-1) mousePosition.y = GlobalRenderer->targetFramebuffer->Height; +} + +void InitPS2Mouse() { + + // enable aux device mouse + outb(0x64, 0xA8); + MouseWait(); + + outb(0x64, 0x20); // tells the keyboard controller we want to send a command to the mouse + MouseWaitInput(); + + uint8_t status = inb(0x60); + status |= 0b10; + MouseWait(); + + outb(0x64, 0x60); + MouseWait(); + + outb(0x60, status); // setting the correct bit in the "compaq" status byte + + MouseWrite(0xF6); // default settings + MouseRead(); + + MouseWrite(0xF4); + MouseRead(); +} \ No newline at end of file diff --git a/kernel/src/userinput/mouse.h b/kernel/src/userinput/mouse.h new file mode 100644 index 0000000..f85beb8 --- /dev/null +++ b/kernel/src/userinput/mouse.h @@ -0,0 +1,19 @@ +#pragma once +#include +#include "../math.h" +#include "../BasicRenderer.h" + +#define PS2LeftButton 0b00000001 +#define PS2MiddleButton 0b00000010 +#define PS2RightButton 0b00000100 + +#define PS2XSign 0b00010000 +#define PS2YSign 0b00100000 +#define PS2XOverflow 0b01000000 +#define PS2YOverflow 0b10000000 + +extern Point mousePosition; + +void InitPS2Mouse(); +void HandlePS2Mouse(uint8_t data); +void ProcessMousePacket(); \ No newline at end of file