#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. }