diff --git a/Makefile b/Makefile index 8c84485..cdada1e 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,6 @@ MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) ROOT_DIR := $(patsubst %/,%,$(dir $(MAKEFILE_PATH))) include tools/make/gcc-cross-compile.mk -include arch/$(ARCH)/config.mk BUILD_DIR := build @@ -14,9 +13,7 @@ BUILD_DIR := build # Architecture-specific source files #################################### -ARCH_C_FILES := $(wildcard arch/$(ARCH)/*.c) -ARCH_ASM_FILES := $(wildcard arch/$(ARCH)/*.S) -ARCH_OBJ := $(addprefix $(BUILD_DIR)/,$(ARCH_C_FILES:.c=.o) $(ARCH_ASM_FILES:.S=.o)) +include arch/$(ARCH)/config.mk #################################### # Platform-independent kernel source files diff --git a/arch/x86_64/acpi/acpi.c b/arch/x86_64/acpi/acpi.c new file mode 100644 index 0000000..948e4a2 --- /dev/null +++ b/arch/x86_64/acpi/acpi.c @@ -0,0 +1,9 @@ +#include +#include + +kern_status_t acpi_init(void) +{ + struct acpi_sdt *fadt = acpi_find_sdt(ACPI_SIG_FADT); + printk("acpi: FADT=%p", fadt); + return KERN_OK; +} diff --git a/arch/x86_64/acpi/rsdp.c b/arch/x86_64/acpi/rsdp.c new file mode 100644 index 0000000..9c554fc --- /dev/null +++ b/arch/x86_64/acpi/rsdp.c @@ -0,0 +1,102 @@ +#include +#include +#include +#include + +static struct acpi_rsdp rsdp; + +static struct acpi_rsdp_10 *search_for_rsdp(void) +{ + uint64_t *start = vm_phys_to_virt(0x80000); + uint64_t *end = vm_phys_to_virt(0xFFFFF); + + for (uint64_t *i = start; i < end; i++) { + if (*i == ACPI_SIG_RSDP) { + return (struct acpi_rsdp_10 *)i; + } + } + + return NULL; +} + +static int init_rsdt(void) +{ + struct acpi_rsdp_10 *x = search_for_rsdp(); + + if (!x) { + printk("acpi: not available"); + return -1; + } + + uint8_t *b = (uint8_t *)x; + size_t chksum = 0; + for (unsigned int i = 0; i < sizeof *x; i++) { + chksum += b[i]; + } + + if (chksum & 0xFF) { + printk("acpi: not available"); + return -1; + } + + if (x->r_revision == 2) { + chksum = 0; + + for (unsigned int i = sizeof *x; i < sizeof(struct acpi_rsdp_20); i++) { + chksum += b[i]; + } + + if (chksum & 0xFF) { + printk("acpi: not available"); + return -1; + } + } + + memcpy(&rsdp.rsdp_20, x, sizeof rsdp.rsdp_20); + return 0; +} + +static struct acpi_sdt *find_via_rsdt(uint32_t sig) +{ + struct acpi_rsdt *rsdt = vm_phys_to_virt(rsdp.rsdp_10.r_rsdt_ptr); + unsigned long nr_tables = (rsdt->r_header.s_length - sizeof(struct acpi_sdt)) / sizeof(uint32_t); + + for (unsigned long i = 0; i < nr_tables; i++) { + struct acpi_sdt *table = vm_phys_to_virt(rsdt->r_tables[i]); + if (*(uint32_t *)table == sig) { + return table; + } + } + + return NULL; +} + +static struct acpi_sdt *find_via_xsdt(uint32_t sig) +{ + struct acpi_xsdt *xsdt = vm_phys_to_virt(rsdp.rsdp_20.r_xsdt_ptr); + unsigned long nr_tables = (xsdt->x_header.s_length - sizeof(struct acpi_sdt)) / sizeof(uint64_t); + + for (unsigned long i = 0; i < nr_tables; i++) { + struct acpi_sdt *table = vm_phys_to_virt(xsdt->x_tables[i]); + if (*(uint32_t *)table == sig) { + return table; + } + } + + return NULL; +} + +struct acpi_sdt *acpi_find_sdt(uint32_t sig) +{ + if (!rsdp.rsdp_10.r_sig[0]) { + if (init_rsdt() != 0) { + return NULL; + } + } + + if (rsdp.rsdp_10.r_revision == 0) { + return find_via_rsdt(sig); + } else { + return find_via_xsdt(sig); + } +} diff --git a/arch/x86_64/config.mk b/arch/x86_64/config.mk index e4a432a..348b80d 100644 --- a/arch/x86_64/config.mk +++ b/arch/x86_64/config.mk @@ -1,2 +1,8 @@ ARCH_CFLAGS := -z max-page-size=0x1000 -m64 -mcmodel=large -mno-red-zone -mno-mmx -mno-sse -mno-sse2 -D_64BIT -DBYTE_ORDER=1234 ARCH_LDFLAGS := -z max-page-size=0x1000 -T arch/x86_64/layout.ld + +ARCH_DIR := arch/$(ARCH) + +ARCH_C_FILES := $(wildcard $(ARCH_DIR)/*.c) $(wildcard $(ARCH_DIR)/acpi/*.c) +ARCH_ASM_FILES := $(wildcard $(ARCH_DIR)/*.S) +ARCH_OBJ := $(addprefix $(BUILD_DIR)/,$(ARCH_C_FILES:.c=.o) $(ARCH_ASM_FILES:.S=.o)) diff --git a/arch/x86_64/include/arch/acpi.h b/arch/x86_64/include/arch/acpi.h new file mode 100644 index 0000000..6da19d5 --- /dev/null +++ b/arch/x86_64/include/arch/acpi.h @@ -0,0 +1,61 @@ +#ifndef ARCH_ACPI_H_ +#define ARCH_ACPI_H_ + +#include +#include +#include + +#define ACPI_SIG_RSDP 0x2052545020445352ULL +#define ACPI_SIG_FADT 0x50434146 + +struct acpi_rsdp_10 { + char r_sig[8]; + uint8_t r_chksum; + char r_oem[6]; + uint8_t r_revision; + uint32_t r_rsdt_ptr; +} __packed; + +struct acpi_rsdp_20 { + struct acpi_rsdp_10 r_base; + + uint32_t r_length; + uint64_t r_xsdt_ptr; + uint8_t r_chksum_ext; + uint8_t r_reserved[3]; +} __packed; + +struct acpi_rsdp { + union { + struct acpi_rsdp_10 rsdp_10; + struct acpi_rsdp_20 rsdp_20; + }; +} __packed; + +struct acpi_sdt { + char s_sig[4]; + uint32_t s_length; + uint8_t s_revision; + uint8_t s_chksum; + char s_oem[6]; + char s_oem_table[8]; + uint32_t s_oem_revision; + uint32_t s_creator; + uint32_t s_creator_revision; +} __packed; + +struct acpi_rsdt { + struct acpi_sdt r_header; + uint32_t r_tables[]; +} __packed; + +struct acpi_xsdt { + struct acpi_sdt x_header; + uint64_t x_tables[]; +} __packed; + +extern kern_status_t acpi_init(void); + +extern struct acpi_sdt *acpi_find_sdt(uint32_t sig); + +#endif diff --git a/arch/x86_64/init.c b/arch/x86_64/init.c index dd96c86..8d1cfb2 100644 --- a/arch/x86_64/init.c +++ b/arch/x86_64/init.c @@ -7,6 +7,7 @@ #include #include #include +#include #define PTR32(x) ((void *)((uintptr_t)(x))) @@ -51,6 +52,8 @@ int ml_init(uintptr_t arg) pmap_bootstrap(); + acpi_init(); + vm_zone_descriptor_t vm_zones[] = { { .zd_id = VM_ZONE_DMA, .zd_node = 0, .zd_name = "dma", .zd_base = 0x00, .zd_limit = 0xffffff }, { .zd_id = VM_ZONE_NORMAL, .zd_node = 0, .zd_name = "normal", .zd_base = 0x1000000, .zd_limit = UINTPTR_MAX },