diff --git a/.vscode/settings.json b/.vscode/settings.json index 8bb680f..ac25aab 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -23,7 +23,8 @@ "string_view": "c", "lapic.h": "c", "spinlock.h": "c", - "fb.h": "c" + "fb.h": "c", + "acpi.h": "c" }, "editor.formatOnPaste": true, "editor.formatOnSave": true, diff --git a/GNUmakefile b/GNUmakefile index 6dd2ae8..ab9a0cd 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -2,7 +2,7 @@ MAKEFLAGS += -rR .SUFFIXES: -QEMUFLAGS := -serial stdio -smp 4 +QEMUFLAGS := -smp 4 USER_QEMUFLAGS ?= IMAGE_NAME := release/emk @@ -15,7 +15,7 @@ all: $(IMAGE_NAME).iso .PHONY: run run: $(IMAGE_NAME).iso ovmf/ovmf-code-x86_64.fd @qemu-system-x86_64 \ - -M q35 \ + -M q35 -serial stdio \ -drive if=pflash,unit=0,format=raw,file=ovmf/ovmf-code-x86_64.fd,readonly=on \ -cdrom $(IMAGE_NAME).iso \ $(QEMUFLAGS) diff --git a/kernel/src/emk.c b/kernel/src/emk.c index d214a92..8c41cab 100644 --- a/kernel/src/emk.c +++ b/kernel/src/emk.c @@ -19,6 +19,7 @@ #endif // FLANTERM_SUPPORT #include #include +#include __attribute__((used, section(".limine_requests"))) static volatile LIMINE_BASE_REVISION(3); __attribute__((used, section(".limine_requests"))) static volatile struct limine_memmap_request memmap_request = { @@ -167,7 +168,7 @@ void emk_entry(void) *c = 32; kfree(c); - /* Setup ACPI (and TODO APIC) */ + /* Setup ACPI */ rsdp_response = rsdp_request.response; if (!rsdp_response) { @@ -175,10 +176,16 @@ void emk_entry(void) } acpi_init(); + /* Disable legacy PIC to prepare for APIC */ + outb(0x21, 0xff); + outb(0xA1, 0xff); + + /* Setup APIC */ + madt_init(); + /* Finished */ log_early("%s", LOG_SEPARATOR); - uint32_t uptime = 0; - log_early("Finished initializing EMK v1.0, took %d seconds", uptime); /* Still not usermode, so keep using log_early */ + log_early("Finished initializing EMK v1.0, took ? seconds"); /* Still not usermode, so keep using log_early */ hlt(); } \ No newline at end of file diff --git a/kernel/src/sys/acpi/madt.c b/kernel/src/sys/acpi/madt.c new file mode 100644 index 0000000..0fbfa9e --- /dev/null +++ b/kernel/src/sys/acpi/madt.c @@ -0,0 +1,56 @@ +/* EMK 1.0 Copyright (c) 2025 Piraterna */ +#include +#include +#include +#include + +acpi_madt_ioapic_t *madt_ioapic_list[256] = {0}; +acpi_madt_ioapic_src_ovr_t *madt_iso_list[256] = {0}; + +uint32_t madt_ioapic_len = 0; +uint32_t madt_iso_len = 0; + +uint64_t lapic_addr = 0; + +void madt_init() +{ + acpi_madt_t *madt = (acpi_madt_t *)acpi_find_table("APIC"); + if (!madt) + { + kpanic(NULL, "Failed to find MADT table"); + } + + if (madt->sdt.length < sizeof(acpi_madt_t)) + { + kpanic(NULL, "MADT table is too small"); + } + + uint64_t offset = 0; + while (offset < madt->sdt.length - sizeof(acpi_madt_t)) + { + acpi_madt_entry_t *entry = (acpi_madt_entry_t *)(madt->table + offset); + + if (entry->length == 0 || offset + entry->length > madt->sdt.length - sizeof(acpi_madt_t)) + { + kpanic(NULL, "Invalid MADT entry length or overflow"); + } + + if (entry->type == MADT_ENTRY_IOAPIC) + { + if (madt_ioapic_len < 256) + madt_ioapic_list[madt_ioapic_len++] = (acpi_madt_ioapic_t *)entry; + } + else if (entry->type == MADT_ENTRY_IOAPIC_SRC_OVR) + { + if (madt_iso_len < 256) + madt_iso_list[madt_iso_len++] = (acpi_madt_ioapic_src_ovr_t *)entry; + } + else if (entry->type == MADT_ENTRY_LAPIC_ADDR_OVR) + { + lapic_addr = ((acpi_madt_lapic_addr_ovr_t *)entry)->lapic_addr; + } + + offset += entry->length; + } + log_early("MADT parsed: %u IOAPIC(s), %u ISO(s), LAPIC addr: 0x%lx", madt_ioapic_len, madt_iso_len, lapic_addr); +} \ No newline at end of file diff --git a/kernel/src/sys/acpi/madt.h b/kernel/src/sys/acpi/madt.h new file mode 100644 index 0000000..e500785 --- /dev/null +++ b/kernel/src/sys/acpi/madt.h @@ -0,0 +1,104 @@ +/* EMK 1.0 Copyright (c) 2025 Piraterna */ +#ifndef MADT_H +#define MADT_H + +#include +#include + +#define MADT_ENTRY_LAPIC 0 /* Local APIC */ +#define MADT_ENTRY_IOAPIC 1 /* I/O APIC */ +#define MADT_ENTRY_IOAPIC_SRC_OVR 2 /* I/O APIC Interrupt Source Override */ +#define MADT_ENTRY_IOAPIC_NMI_SRC 3 /* I/O APIC Non-Maskable Interrupt Source */ +#define MADT_ENTRY_LAPIC_NMI 4 /* Local APIC Non-Maskable Interrupt */ +#define MADT_ENTRY_LAPIC_ADDR_OVR 5 /* Local APIC Address Override */ +#define MADT_ENTRY_LX2APIC 9 /* Local x2APIC */ + +typedef struct acpi_madt +{ + acpi_sdt_header_t sdt; + uint32_t lapic_base; + uint32_t flags; + char table[]; +} __attribute__((packed)) acpi_madt_t; + +typedef struct acpi_madt_entry +{ + uint8_t type; + uint8_t length; +} __attribute__((packed)) acpi_madt_entry_t; + +/* Entry Type 0: Processor Local APIC */ +typedef struct acpi_madt_lapic +{ + acpi_madt_entry_t header; + uint8_t acpi_proc_id; /* ACPI Processor ID */ + uint8_t apic_id; /* APIC ID */ + uint32_t flags; /* Bit 0: Processor Enabled, Bit 1: Online Capable */ +} __attribute__((packed)) acpi_madt_lapic_t; + +/* Entry Type 1: I/O APIC */ +typedef struct acpi_madt_ioapic +{ + acpi_madt_entry_t header; + uint8_t ioapic_id; /* I/O APIC's ID */ + uint8_t reserved; /* Reserved (0) */ + uint32_t ioapic_addr; /* I/O APIC Address */ + uint32_t gsi_base; /* Global System Interrupt Base */ +} __attribute__((packed)) acpi_madt_ioapic_t; + +/* Entry Type 2: I/O APIC Interrupt Source Override */ +typedef struct acpi_madt_ioapic_src_ovr +{ + acpi_madt_entry_t header; + uint8_t bus_source; /* Bus Source */ + uint8_t irq_source; /* IRQ Source */ + uint32_t gsi; /* Global System Interrupt */ + uint16_t flags; /* Flags */ +} __attribute__((packed)) acpi_madt_ioapic_src_ovr_t; + +/* Entry Type 3: I/O APIC Non-Maskable Interrupt Source */ +typedef struct acpi_madt_ioapic_nmi_src +{ + acpi_madt_entry_t header; + uint8_t nmi_source; /* NMI Source */ + uint8_t reserved; /* Reserved */ + uint16_t flags; /* Flags */ + uint32_t gsi; /* Global System Interrupt */ +} __attribute__((packed)) acpi_madt_ioapic_nmi_src_t; + +/* Entry Type 4: Local APIC Non-Maskable Interrupt */ +typedef struct acpi_madt_lapic_nmi +{ + acpi_madt_entry_t header; + uint8_t acpi_proc_id; /* ACPI Processor ID (0xFF for all processors) */ + uint16_t flags; /* Flags */ + uint8_t lint; /* LINT# (0 or 1) */ +} __attribute__((packed)) acpi_madt_lapic_nmi_t; + +/* Entry Type 5: Local APIC Address Override */ +typedef struct acpi_madt_lapic_addr_ovr +{ + acpi_madt_entry_t header; + uint16_t reserved; /* Reserved */ + uint64_t lapic_addr; /* 64-bit Physical Address of Local APIC */ +} __attribute__((packed)) acpi_madt_lapic_addr_ovr_t; + +/* Entry Type 9: Processor Local x2APIC */ +typedef struct acpi_madt_lx2apic +{ + acpi_madt_entry_t header; + uint16_t reserved; + uint32_t x2apic_id; /* Processor's Local x2APIC ID */ + uint32_t flags; /* Flags (same as Local APIC) */ + uint32_t acpi_id; /* ACPI ID */ +} __attribute__((packed)) acpi_madt_lx2apic_t; + +extern acpi_madt_ioapic_t *madt_ioapic_list[256]; +extern acpi_madt_ioapic_src_ovr_t *madt_iso_list[256]; +extern uint32_t madt_ioapic_len; +extern uint32_t madt_iso_len; +extern uint64_t lapic_addr; + +void madt_init(); + +#endif // MADT_H \ No newline at end of file