Include file restructure!

- include/ now has subdirs
- standard C headers will be in 'include/c'. Any program can include these
- all other header shall only be used by the kernel
This commit is contained in:
2024-05-07 21:01:50 +02:00
parent 41e0b93f52
commit 7826b9b7d4
20 changed files with 33 additions and 83 deletions
+185
View File
@@ -0,0 +1,185 @@
#ifndef ISRS_H
#define ISRS_H
#include <interrupt/idt.h>
#include <screen/text.h>
// Exception handlers
__attribute__ ((interrupt))
void excp_divideErr(intFrame_t* iframe) { // ISR 0
fgColor = RED;
print("[ Division Error ]\n");
__asm__ volatile ("cli; hlt"); // Halt system
}
__attribute__ ((interrupt))
void excp_debugErr(intFrame_t* iframe) { // ISR 1
fgColor = RED;
print("[ Debug Exception ]\n");
__asm__ volatile ("cli; hlt");
}
__attribute__ ((interrupt))
void excp_nmiInterrupt(intFrame_t* iframe) { // ISR 2
fgColor = RED;
print("[ Non-maskable Interrupt ]\n");
__asm__ volatile ("cli; hlt");
}
__attribute__ ((interrupt))
void excp_breakpoint(intFrame_t* iframe) { // ISR 3
fgColor = RED;
print("[ Breakpoint ]\n");
__asm__ volatile ("cli; hlt");
}
__attribute__ ((interrupt))
void excp_overflow(intFrame_t* iframe) { // ISR 4
fgColor = RED;
print("[ Overflow Error ]\n");
__asm__ volatile ("cli; hlt");
}
__attribute__ ((interrupt))
void excp_boundRangeExceed(intFrame_t* iframe) { // ISR 5
fgColor = RED;
print("[ Bound Range Exceeded ]\n");
__asm__ volatile ("cli; hlt");
}
__attribute__ ((interrupt))
void excp_invalidOpcode(intFrame_t* iframe) { // ISR 6
fgColor = RED;
print("[ Invalid OpCode ]\n");
__asm__ volatile ("cli; hlt");
}
__attribute__ ((interrupt))
void excp_deviceNA(intFrame_t* iframe) { // ISR 7
fgColor = RED;
print("[ Device Not Available ]\n");
__asm__ volatile ("cli; hlt");
}
__attribute__ ((interrupt))
void excp_doubleFault(intFrame_t* iframe, uint32_t errCode) { // ISR 8
fgColor = RED;
print("[ Double Fault : 0x");
print(itoa(errCode, 16));
print(" ]\n");
__asm__ volatile ("cli; hlt");
}
__attribute__ ((interrupt))
void excp_coprocOverrun(intFrame_t* iframe) { // ISR 9
fgColor = RED;
print("[ Coprocessor Segment Overrun ]\n");
__asm__ volatile ("cli; hlt");
}
__attribute__ ((interrupt))
void excp_invalidTss(intFrame_t* iframe, uint32_t errCode) { // ISR 10
fgColor = RED;
print("[ Invalid TSS : 0x");
print(itoa(errCode, 16));
print(" ]\n");
__asm__ volatile ("cli; hlt");
}
__attribute__ ((interrupt))
void excp_noSegment(intFrame_t* iframe, uint32_t errCode) { // ISR 11
fgColor = RED;
print("[ Segment Not Present : 0x");
print(itoa(errCode, 16));
print(" ]\n");
__asm__ volatile ("cli; hlt");
}
__attribute__ ((interrupt))
void excp_stackSegmentFault(intFrame_t* iframe, uint32_t errCode) { // ISR 12
fgColor = RED;
print("[ Stack-Segment Fault : 0x");
print(itoa(errCode, 16));
print(" ]\n");
__asm__ volatile ("cli; hlt");
}
__attribute__ ((interrupt))
void excp_generalProtectionFault(intFrame_t* iframe, uint32_t errCode) { // ISR 13
fgColor = RED;
print("[ General Protection Fault : 0x");
print(itoa(errCode, 16));
print(" ]\n");
__asm__ volatile ("cli; hlt");
}
__attribute__ ((interrupt))
void excp_pageFault(intFrame_t* iframe, uint32_t errCode) { // ISR 14
fgColor = RED;
print("[ Page Fault : 0x");
print(itoa(errCode, 16));
print(" ]\n");
__asm__ volatile ("cli; hlt");
}
__attribute__ ((interrupt))
void excp_reserved(intFrame_t* iframe) { // ISR 15
fgColor = RED;
print("[ Reserved Exception ]\n"); // Shouldn't get this one
__asm__ volatile ("cli; hlt");
}
__attribute__ ((interrupt))
void excp_floatingPointErr(intFrame_t* iframe) { // ISR 16
fgColor = RED;
print("[ x87 FPU Floating-Point Error ]\n");
__asm__ volatile ("cli; hlt");
}
__attribute__ ((interrupt))
void excp_alignCheck(intFrame_t* iframe, uint32_t errCode) { // ISR 17
fgColor = RED;
print("[ Alignment Check : 0x");
print(itoa(errCode, 16));
print(" ]\n");
__asm__ volatile ("cli; hlt");
}
__attribute__ ((interrupt))
void excp_machineCheck(intFrame_t* iframe) { // ISR 18
fgColor = RED;
print("[ Machine Check ]\n");
__asm__ volatile ("cli; hlt");
}
// TODO: Add more (because there's always more)
// Repetative isr definitions
void setupExceptions() {
for (uint8_t i = 0; i < 32; i++) {
idtSetGate(i, excp_reserved, TRAP_GATE_FLAGS);
}
idtSetGate(0, excp_divideErr, TRAP_GATE_FLAGS);
idtSetGate(1, excp_debugErr, TRAP_GATE_FLAGS);
idtSetGate(2, excp_nmiInterrupt, TRAP_GATE_FLAGS);
idtSetGate(3, excp_breakpoint, TRAP_GATE_FLAGS);
idtSetGate(4, excp_overflow, TRAP_GATE_FLAGS);
idtSetGate(5, excp_boundRangeExceed, TRAP_GATE_FLAGS);
idtSetGate(6, excp_invalidOpcode, TRAP_GATE_FLAGS);
idtSetGate(7, excp_deviceNA, TRAP_GATE_FLAGS);
idtSetGate(8, excp_doubleFault, TRAP_GATE_FLAGS);
idtSetGate(9, excp_coprocOverrun, TRAP_GATE_FLAGS);
idtSetGate(10, excp_invalidTss, TRAP_GATE_FLAGS);
idtSetGate(11, excp_noSegment, TRAP_GATE_FLAGS);
idtSetGate(12, excp_stackSegmentFault, TRAP_GATE_FLAGS);
idtSetGate(13, excp_generalProtectionFault, TRAP_GATE_FLAGS);
idtSetGate(14, excp_pageFault, TRAP_GATE_FLAGS);
idtSetGate(15, excp_reserved, TRAP_GATE_FLAGS);
idtSetGate(16, excp_floatingPointErr, TRAP_GATE_FLAGS);
idtSetGate(17, excp_alignCheck, TRAP_GATE_FLAGS);
idtSetGate(18, excp_machineCheck, TRAP_GATE_FLAGS);
// Other are reserved
}
#endif
+55
View File
@@ -0,0 +1,55 @@
#ifndef IDT_H
#define IDT_H
#include <stdint.h>
#include <screen/text.h>
#define TRAP_GATE_FLAGS 0x8f // P = 1, DPL = 00, S = 0, Type = 1111 (32-bit Trap gate)
#define INT_GATE_FLAGS 0x8e // P = 1, DPL = 00, S = 0, Type = 1110 (32-bit Int gate)
#define USR_INT_GAME_FLAGS 0xee // P = 1, DPL = 11, S = 0, Type = 1110 (32-bit Int gate)
typedef struct {
uint16_t offsetLow;
uint16_t selector;
uint8_t zero;
uint8_t typeAttr;
uint16_t offsetHigh;
} __attribute__ ((packed)) idtEntry_t;
typedef struct {
uint16_t limit;
uint32_t base;
} __attribute__ ((packed)) idtp_t;
typedef struct {
uint32_t eip;
uint32_t cs;
uint32_t eflags;
uint32_t esp;
uint32_t ss;
} __attribute__ ((packed)) intFrame_t;
__attribute__ ((aligned(0x10))) // For performance
idtEntry_t idt[256] = { 0 };
idtp_t idtp;
void idtSetGate(uint8_t i, void* handler, uint8_t flags) {
uint32_t offset = (uint32_t)handler;
idtEntry_t* entry = &idt[i];
entry->offsetLow = (uint16_t)offset;
entry->selector = 0x08;
entry->zero = 0;
entry->typeAttr = flags;
entry->offsetHigh = (uint16_t)(offset >> 16);
}
void setupIdt() {
idtp.limit = sizeof(idtEntry_t) * 256;
idtp.base = (uint32_t)&idt;
__asm__ volatile ("lidt %0" : : "m"(idtp));
}
#endif
+95
View File
@@ -0,0 +1,95 @@
#ifndef PIC_H
#define PIC_H
#include <ports/io.h>
// PIC I/O Ports
#define PIC_1_CMD 0x20
#define PIC_1_DATA 0x21
#define PIC_2_CMD 0xA0
#define PIC_2_DATA 0xA1
// IRQs
#define NEW_IRQ_0 0x20 // IRQ 0 : int 32
#define NEW_IRQ_8 0x28 // IRQ 8 : int 40
// Commands
#define PIC_EOI 0x20 // End Of Interrupt
#define PIC_DISABLE 0xff
void sendPicEOI(uint8_t irq) {
if (irq >= 8) {
outb(PIC_2_CMD, PIC_EOI);
}
outb(PIC_1_CMD, PIC_EOI);
}
void disableIrqs() {
outb(PIC_2_DATA, PIC_DISABLE);
outb(PIC_1_DATA, PIC_DISABLE);
}
void setIrqMask(uint8_t irq) {
uint16_t port;
uint8_t value;
if (irq < 8) {
port = PIC_1_DATA;
} else {
irq -= 8;
port = PIC_2_DATA;
}
value = inb(port) | (1 << irq);
outb(port, value);
}
void unsetIrqMask(uint8_t irq) {
uint16_t port;
uint8_t value;
if (irq < 8) {
port = PIC_1_DATA;
} else {
irq -= 8;
port = PIC_2_DATA;
}
value = inb(port) & ~(1 << irq);
outb(port, value);
}
void remapPic() {
uint8_t pic1Mask = inb(PIC_1_DATA);
uint8_t pic2Mask = inb(PIC_2_DATA);
// Send Init Control Word 1-4 to both PICs
// ICW 1: bit 0 - send up to 4 ICWs, bit 4 - Init PIC
outb(PIC_1_CMD, 0x11);
ioWait(); // For slower machines
outb(PIC_2_CMD, 0x11);
ioWait();
// ICW 2: Where to map IRW bases in IDT
outb(PIC_1_DATA, NEW_IRQ_0);
ioWait();
outb(PIC_2_DATA, NEW_IRQ_8);
ioWait();
// ICW 3: Which IRQ in PIC1 is PIC2; Mapping PIC2 to IRQ 2
outb(PIC_1_DATA, 0x04);
ioWait();
outb(PIC_2_DATA, 0x02);
ioWait();
// ICW 4 - Set x86 mode
outb(PIC_1_DATA, 0x01);
ioWait();
outb(PIC_2_DATA, 0x01);
ioWait();
outb(PIC_1_DATA, pic1Mask);
outb(PIC_2_DATA, pic2Mask);
}
#endif
+47
View File
@@ -0,0 +1,47 @@
#ifndef TIMER_H
#define TIMER_H
#include <stdint.h>
#include <interrupt/idt.h>
#include <interrupt/pic.h>
#include <screen/text.h>
#define CHANNEL_0 0x40 // Offset it by 1 or 2 for ch1 and ch2
#define COMMAND 0x43
#define INPUT_CLK 1193182
static uint32_t* timerTicks = (uint32_t*)0x1000;
__attribute__ ((interrupt))
void timerHandler(intFrame_t* iframe) {
*timerTicks += 1;
// TODO: Improve the cursor rendering
if (*timerTicks % 500 == 0) putcAt(' ', cursor.x, cursor.y);
else if (*timerTicks % 250 == 0) putcAt(127, cursor.x, cursor.y);
sendPicEOI(0);
}
void setPitPhase(uint8_t channel, uint8_t opMode, uint16_t hz) {
if (channel > 2 || opMode > 7) { return; }
__asm__ volatile ("cli");
// Send command - bits 7-6 channel, 5-4 Access mode, 3-1 operating mode, 0 - Should be zero in x86
outb(COMMAND, ((channel << 6) | (3 << 4) | (opMode << 1)));
// Send frequency
uint16_t freq = INPUT_CLK / hz; // I solved an equation to figure this out
outb(CHANNEL_0 + channel, (uint8_t)freq);
outb(CHANNEL_0 + channel, (uint8_t)(freq >> 8));
__asm__ volatile ("sti");
}
void setupTimer() { // Sets up IRQ 0 - PIT
idtSetGate(0x20, timerHandler, INT_GATE_FLAGS);
unsetIrqMask(0);
setPitPhase(0, 2, 1000); // Default setup: 1000Hz - 1 tick per 1ms
}
#endif
+75
View File
@@ -0,0 +1,75 @@
#ifndef SYSCALL_H
#define SYSCALL_H
#include <interrupt/pit.h>
// System call count
#define MAX_SYSCALLS 2
// Args: ebx - number of miliseconds
void sys_sleep() {
uint32_t ms;
__asm__ volatile ("movl %%ebx, %0" : "=r"(ms));
uint32_t requiredTicks = *timerTicks + ms;
while (*timerTicks != requiredTicks) { // Wait...
__asm__ volatile ("sti;hlt;cli;");
}
}
// System call table
void* syscalls[MAX_SYSCALLS] = {
sys_sleep,
};
// int 0x80 - Syscall interrupt, handled by this function
// eax : Syscall number
__attribute__ ((naked)) // No prologue or epilogue, just assembly
void syscallHandler(void) {
// Interrupt - Stack should contain: ss, esp, eflags, cs, eip
// We should also push these regs: ax, gs, fs, es, ds, bp, di, si, dx, cx, bx
__asm__ volatile (
".intel_syntax noprefix\n" // We use intel syntax
".equ MAX_SYSCALLS, 2\n" // Define MAX_SYSCALLS again
// Check if syscall exists
"cmp eax, MAX_SYSCALLS - 1\n"
"ja invalidSyscall\n"
// Call the syscall
"push eax\n" // Push required values
"push gs\n"
"push fs\n"
"push es\n"
"push ds\n"
"push ebp\n"
"push edi\n"
"push esi\n"
"push edx\n"
"push ecx\n"
"push ebx\n"
"push esp\n" // Push stack pointer again (for variables and such idk)
"call [syscalls + eax * 4]\n" // Call syscall from table. Syscall number should be in eax
"add esp, 4\n"
"pop ebx\n" // Pop pushed values
"pop ecx\n"
"pop edx\n"
"pop esi\n"
"pop edi\n"
"pop ebp\n"
"pop ds\n"
"pop es\n"
"pop fs\n"
"pop gs\n"
"add esp, 4\n" // Save eax value
"iretd\n" // Return from interrupt
// TODO: Send an error or something here
"invalidSyscall:\n"
"iretd\n"
".att_syntax" // Switch back to Att Syntax (Just in case)
);
}
#endif