From 4151de51d984e8179bbe01dfa78bf3a118957967 Mon Sep 17 00:00:00 2001 From: Kevin Alavik Date: Thu, 15 May 2025 22:34:16 +0200 Subject: [PATCH] feat/kernel: Started on basic bootstrap ACPI --- kernel/GNUmakefile | 2 + kernel/src/boot/emk.h | 1 + kernel/src/emk.c | 15 +++++ kernel/src/lib/string.c | 19 +++++++ kernel/src/lib/string.h | 2 + kernel/src/sys/acpi.c | 122 ++++++++++++++++++++++++++++++++++++++++ kernel/src/sys/acpi.h | 47 ++++++++++++++++ 7 files changed, 208 insertions(+) create mode 100644 kernel/src/sys/acpi.c create mode 100644 kernel/src/sys/acpi.h diff --git a/kernel/GNUmakefile b/kernel/GNUmakefile index 04a90ba..6d3fcef 100644 --- a/kernel/GNUmakefile +++ b/kernel/GNUmakefile @@ -53,11 +53,13 @@ endif CPPFLAGS := -I../external -I$(SRCDIR) -MMD -MP -DLIMINE_API_REVISION=3 IMPLICIT_SRCS := +ifneq ($(MAKECMDGOALS),menuconfig) ifeq ($(CONFIG_KERNEL_HEAP_FF),y) IMPLICIT_SRCS += src/mm/heap/ff.c else $(error Error: No heap algorithm was defined. Please run "make menuconfig" and select one.) endif +endif ifeq ($(CONFIG_ENABLE_FLANTERM),y) IMPLICIT_SRCS += ../external/flanterm/flanterm.c diff --git a/kernel/src/boot/emk.h b/kernel/src/boot/emk.h index f78d7d5..bf82d3b 100644 --- a/kernel/src/boot/emk.h +++ b/kernel/src/boot/emk.h @@ -15,6 +15,7 @@ extern uint64_t kvirt; extern uint64_t kphys; extern uint64_t kstack_top; extern vctx_t *kvm_ctx; +extern struct limine_rsdp_response *rsdp_response; #define HIGHER_HALF(ptr) ((void *)((uint64_t)(ptr) < hhdm_offset ? (uint64_t)(ptr) + hhdm_offset : (uint64_t)(ptr))) #define PHYSICAL(ptr) ((void *)((uint64_t)(ptr) >= hhdm_offset ? (uint64_t)(ptr) - hhdm_offset : (uint64_t)(ptr))) diff --git a/kernel/src/emk.c b/kernel/src/emk.c index e3d3a76..c25685e 100644 --- a/kernel/src/emk.c +++ b/kernel/src/emk.c @@ -17,6 +17,7 @@ #include #include #endif // FLANTERM_SUPPORT +#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 = { @@ -33,6 +34,9 @@ __attribute__((used, section(".limine_requests"))) volatile struct limine_frameb .id = LIMINE_FRAMEBUFFER_REQUEST, .response = 0}; #endif // FLANTERM_SUPPORT +__attribute__((used, section(".limine_requests"))) static volatile struct limine_rsdp_request rsdp_request = { + .revision = 0, + .id = LIMINE_RSDP_REQUEST}; __attribute__((used, section(".limine_requests_start"))) static volatile LIMINE_REQUESTS_START_MARKER; __attribute__((used, section(".limine_requests_end"))) static volatile LIMINE_REQUESTS_END_MARKER; @@ -42,6 +46,7 @@ uint64_t kvirt = 0; uint64_t kphys = 0; uint64_t kstack_top = 0; vctx_t *kvm_ctx = NULL; +struct limine_rsdp_response *rsdp_response = NULL; #if FLANTERM_SUPPORT struct flanterm_context *ft_ctx = NULL; @@ -89,6 +94,7 @@ void emk_entry(void) idt_init(); log_early("Initialized IDT"); + /* Setup physical memory*/ if (!hhdm_request.response) { kpanic(NULL, "Failed to get HHDM request"); @@ -156,5 +162,14 @@ void emk_entry(void) kfree(c); log_early("Initialized kernel heap"); + /* Setup ACPI and APIC */ + rsdp_response = rsdp_request.response; + if (!rsdp_response) + { + kpanic(NULL, "Failed to get RSDP request"); + } + acpi_init(); + log_early("Initialized ACPI"); + hlt(); } \ No newline at end of file diff --git a/kernel/src/lib/string.c b/kernel/src/lib/string.c index 12f0ab4..d49fa05 100644 --- a/kernel/src/lib/string.c +++ b/kernel/src/lib/string.c @@ -63,4 +63,23 @@ int memcmp(const void *s1, const void *s2, size_t n) } return 0; +} + +int strncmp(const char *s1, const char *s2, size_t n) +{ + while (n > 0 && *s1 && *s2) + { + if (*s1 != *s2) + { + return (unsigned char)*s1 - (unsigned char)*s2; + } + s1++; + s2++; + n--; + } + if (n == 0) + { + return 0; + } + return (unsigned char)*s1 - (unsigned char)*s2; } \ No newline at end of file diff --git a/kernel/src/lib/string.h b/kernel/src/lib/string.h index 9dac15d..b0c1dc7 100644 --- a/kernel/src/lib/string.h +++ b/kernel/src/lib/string.h @@ -10,4 +10,6 @@ void *memset(void *s, int c, size_t n); void *memmove(void *dest, const void *src, size_t n); int memcmp(const void *s1, const void *s2, size_t n); +int strncmp(const char *s1, const char *s2, size_t n); + #endif // STRING_H \ No newline at end of file diff --git a/kernel/src/sys/acpi.c b/kernel/src/sys/acpi.c new file mode 100644 index 0000000..a73a2c6 --- /dev/null +++ b/kernel/src/sys/acpi.c @@ -0,0 +1,122 @@ +/* EMK 1.0 Copyright (c) 2025 Piraterna */ +#include +#include +#include +#include +#include + +static int acpi_uses_xsdt = 0; +static void *acpi_rsdt_ptr = NULL; + +static uint8_t acpi_checksum(void *ptr, size_t len) +{ + uint8_t sum = 0; + uint8_t *data = (uint8_t *)ptr; + for (size_t i = 0; i < len; i++) + { + sum += data[i]; + } + return sum; +} + +static int acpi_validate_rsdp(acpi_rsdp_t *rsdp) +{ + return acpi_checksum(rsdp, sizeof(acpi_rsdp_t)) == 0; +} + +static int acpi_validate_xsdp(acpi_xsdp_t *xsdp) +{ + if (acpi_checksum(xsdp, sizeof(acpi_rsdp_t)) != 0) + return 0; + if (acpi_checksum(xsdp, xsdp->length) != 0) + return 0; + return 1; +} + +void acpi_init(void) +{ + if (!rsdp_response || !rsdp_response->address) + { + kpanic(NULL, "No RSDP provided"); + } + + acpi_rsdp_t *rsdp = (acpi_rsdp_t *)rsdp_response->address; + log_early("RSDP found at %p", rsdp); + if (strncmp(rsdp->signature, "RSD PTR ", 8) != 0) + { + kpanic(NULL, "Invalid RSDP signature"); + } + + if (rsdp->revision >= 2) + { + acpi_xsdp_t *xsdp = (acpi_xsdp_t *)rsdp; + if (!acpi_validate_xsdp(xsdp)) + { + kpanic(NULL, "XSDP checksum validation failed"); + } + acpi_uses_xsdt = 1; + acpi_rsdt_ptr = (void *)(uintptr_t)xsdp->xsdt_address; + } + else + { + if (!acpi_validate_rsdp(rsdp)) + { + kpanic(NULL, "RSDP checksum validation failed"); + } + acpi_uses_xsdt = 0; + acpi_rsdt_ptr = (void *)(uintptr_t)rsdp->rsdt_address; + } + + /* Validate RSDT/XSDT header */ + acpi_sdt_header_t *sdt = (acpi_sdt_header_t *)acpi_rsdt_ptr; + if (acpi_checksum(sdt, sdt->length) != 0) + { + kpanic(NULL, "RSDT/XSDT checksum validation failed"); + } + + log_early("ACPI initialized, using %s at %p", + acpi_uses_xsdt ? "XSDT" : "RSDT", acpi_rsdt_ptr); +} + +void *acpi_find_table(const char *name) +{ + if (!acpi_rsdt_ptr || !name) + return NULL; + + acpi_sdt_header_t *sdt = (acpi_sdt_header_t *)acpi_rsdt_ptr; + uint32_t entries; + + if (acpi_uses_xsdt) + { + entries = (sdt->length - sizeof(acpi_sdt_header_t)) / sizeof(uint64_t); + } + else + { + entries = (sdt->length - sizeof(acpi_sdt_header_t)) / sizeof(uint32_t); + } + + for (uint32_t i = 0; i < entries; i++) + { + acpi_sdt_header_t *table; + if (acpi_uses_xsdt) + { + uint64_t *xsdt_entries = (uint64_t *)(sdt + 1); + table = (acpi_sdt_header_t *)(uintptr_t)xsdt_entries[i]; + } + else + { + uint32_t *rsdt_entries = (uint32_t *)(sdt + 1); + table = (acpi_sdt_header_t *)(uintptr_t)rsdt_entries[i]; + } + + if (strncmp(table->signature, name, 4) == 0) + { + if (acpi_checksum(table, table->length) == 0) + { + return table; + } + } + } + + return NULL; +} \ No newline at end of file diff --git a/kernel/src/sys/acpi.h b/kernel/src/sys/acpi.h new file mode 100644 index 0000000..3a87048 --- /dev/null +++ b/kernel/src/sys/acpi.h @@ -0,0 +1,47 @@ +/* EMK 1.0 Copyright (c) 2025 Piraterna */ +#ifndef EMK_ACPI_H +#define EMK_ACPI_H + +#include +#include +#include + +typedef struct acpi_rsdp +{ + char signature[8]; + uint8_t checksum; + char oem_id[6]; + uint8_t revision; + uint32_t rsdt_address; +} __attribute__((packed)) acpi_rsdp_t; + +typedef struct acpi_xsdp +{ + char signature[8]; + uint8_t checksum; + char oem_id[6]; + uint8_t revision; + uint32_t rsdt_address; + uint32_t length; + uint64_t xsdt_address; + uint8_t full_checksum; + uint8_t reserved[3]; +} __attribute__((packed)) acpi_xsdp_t; + +typedef struct acpi_sdt_header +{ + char signature[4]; + uint32_t length; + uint8_t revision; + uint8_t checksum; + char oem_id[6]; + char oem_table_id[8]; + uint32_t oem_revision; + uint32_t creator_id; + uint32_t creator_revision; +} __attribute__((packed)) acpi_sdt_header_t; + +void *acpi_find_table(const char *name); +void acpi_init(void); + +#endif /* EMK_ACPI_H */ \ No newline at end of file