From 2fe554dffdc6915409d4f9c8200390c4cadbcc1f Mon Sep 17 00:00:00 2001 From: Nicholas Orlowsky Date: Sun, 2 Feb 2025 12:45:16 -0500 Subject: [PATCH] ditto --- kernel/rsdp.c | 196 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 kernel/rsdp.c diff --git a/kernel/rsdp.c b/kernel/rsdp.c new file mode 100644 index 0000000..0af34ee --- /dev/null +++ b/kernel/rsdp.c @@ -0,0 +1,196 @@ +#pragma once +#include +#include "memory.c" +#include "vga.c" + +struct rsdp_t { + char signature[8]; + uint8_t checksum; + char oem_id[6]; + uint8_t revision; + uint32_t rsdt_address; +} __attribute__ ((packed)); + +struct xsdp_t { + char signature[8]; + uint8_t checksum; + char oem_id[6]; + uint8_t revision; + uint32_t unused; + uint32_t length; + uint32_t xsdt_addr_hi; + uint32_t xsdt_addr_lo; + uint8_t checksum_ext; + uint8_t unused_[3] +} __attribute__ ((packed)); + +struct acpi_header_t { + 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_division; +} __attribute__ ((packed)); + +struct GenericAddressStructure +{ + uint8_t AddressSpace; + uint8_t BitWidth; + uint8_t BitOffset; + uint8_t AccessSize; + uint64_t Address; +}; + +struct fadt_t +{ + struct acpi_header_t header; + uint32_t firmware_ctl; + uint32_t dsdt_ptr; + + uint8_t reserved; + + uint8_t PreferredPowerManagementProfile; + uint16_t SCI_Interrupt; + uint32_t SMI_CommandPort; + uint8_t AcpiEnable; + uint8_t AcpiDisable; + uint8_t S4BIOS_REQ; + uint8_t PSTATE_Control; + uint32_t PM1aEventBlock; + uint32_t PM1bEventBlock; + uint32_t PM1aControlBlock; + uint32_t PM1bControlBlock; + uint32_t PM2ControlBlock; + uint32_t PMTimerBlock; + uint32_t GPE0Block; + uint32_t GPE1Block; + uint8_t PM1EventLength; + uint8_t PM1ControlLength; + uint8_t PM2ControlLength; + uint8_t PMTimerLength; + uint8_t GPE0Length; + uint8_t GPE1Length; + uint8_t GPE1Base; + uint8_t CStateControl; + uint16_t WorstC2Latency; + uint16_t WorstC3Latency; + uint16_t FlushSize; + uint16_t FlushStride; + uint8_t DutyOffset; + uint8_t DutyWidth; + uint8_t DayAlarm; + uint8_t MonthAlarm; + uint8_t Century; + + // reserved in ACPI 1.0; used since ACPI 2.0+ + uint16_t BootArchitectureFlags; + + uint8_t Reserved2; + uint32_t Flags; + + // 12 byte structure; see below for details + struct GenericAddressStructure ResetReg; + + uint8_t ResetValue; + uint8_t Reserved3[3]; + + // 64bit pointers - Available on ACPI 2.0+ + uint64_t X_FirmwareControl; + uint64_t X_Dsdt; + + struct GenericAddressStructure X_PM1aEventBlock; + struct GenericAddressStructure X_PM1bEventBlock; + struct GenericAddressStructure X_PM1aControlBlock; + struct GenericAddressStructure X_PM1bControlBlock; + struct GenericAddressStructure X_PM2ControlBlock; + struct GenericAddressStructure X_PMTimerBlock; + struct GenericAddressStructure X_GPE0Block; + struct GenericAddressStructure X_GPE1Block; +}; + +struct rsdt_t { + struct acpi_header_t header; + uint32_t pointer[64]; +}; + + + + +uint8_t validate(struct rsdp_t *ptr) { + char sig[] = "RSD PTR "; + if (!memseq(ptr->signature, sig, 8)) return 0; + + uint8_t *rsdp_bytes = (uint8_t *) ptr; + uint8_t sum = 0; + for(uint8_t i = 0; i < 20; i++) { + sum += rsdp_bytes[i]; + } + + if (sum == 0 && ptr->revision == 2) { + printf_nolock("ACPI v2+ not yet supported :(\n"); + for(;;){} + // TODO: test with ACPI 2 System + struct xsdp_t *r2_ptr = (struct xsdp_t*) ptr; + + uint8_t *xsdp_bytes = ((uint8_t *) r2_ptr) + 8; + uint8_t x_sum = 0; + for(uint8_t i = 0; i < 16; i++) { + sum += xsdp_bytes[i]; + } + } + + return sum == 0; +} + +char* find_table(struct rsdt_t* table, char* sig) { + uint32_t entries = (table->header.length - sizeof table->header) / 4; + for (uint32_t i = 0; i < entries; i++) { + struct acpi_header_t* entry = (struct acpi_header_t*) table->pointer[i]; + if (memseq(entry->signature, sig, 4)) { + printf_nolock("Found %s / %s\n", entry->oem_id, entry->signature); + printf_nolock("Signature: %s\n", entry->signature); + printf_nolock("Length : %d\n", entry->length); + printf_nolock("Oem ID : %s\n", entry->oem_id); + printf_nolock("Checksum : %d\n", entry->checksum); + return (void*)entry; + } + } + + printf_nolock("Not Found"); + return 0; +} + +void find_rsdp() { + struct rsdp_t *ptr; + + volatile uint8_t found = 0; + for (uint32_t addr = 0x00000000; addr <= 0x000FFFFF; addr++) { + ptr = (struct rsdp_t *) addr; + + if (validate(ptr)) { + found = 1; + break; + } + } + + if (!found) { + uint8_t* ebda = (uint8_t*)(*((uint16_t*)0x40e) << 4); + for (uint32_t i = 0; i <= 1024; i += 16) { + ptr = (struct rsdp_t*) ebda; + if (validate(ptr)) { + found = 1; + break; + } + } + } + + printf_nolock("RSDP Found %s / %s / %d\n", ptr->oem_id, ptr->signature); + + struct fadt_t* fadt = (struct fadt_t*) find_table((struct rsdt_t*) ptr->rsdt_address, "FACP"); + + facp. +}