//----------------------------------------------------------------------------// // GNU GPL OS/K // // // // Desc: ACPI, Hardware detection related functions // // // // // // Copyright © 2018-2019 The OS/K Team // // // // This file is part of OS/K. // // // // OS/K is free software: you can redistribute it and/or modify // // it under the terms of the GNU General Public License as published by // // the Free Software Foundation, either version 3 of the License, or // // any later version. // // // // OS/K is distributed in the hope that it will be useful, // // but WITHOUT ANY WARRANTY//without even the implied warranty of // // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // // GNU General Public License for more details. // // // // You should have received a copy of the GNU General Public License // // along with OS/K. If not, see . // //----------------------------------------------------------------------------// #include #include #include #include SDTHeader *AcpiSDT = NULL; SDTHeader *AcpiFADT = NULL; char IoACPIVersion = 1; // // Returns the checksum of the given structure // static inline char DoChecksum(void *ptr, size_t size, size_t intermediateSize, ulong reason) { char checksum = 0; for (ulong i=0; i < (ulong)size; i++) { if (reason && i > (ulong)intermediateSize) break; checksum += (uchar)((char*)ptr)[i]; } return checksum; } // // Returns the address of the RSDP // static inline RSDPDescriptor *IoFindRSDP() { char *rsdp = NULL; // Search in EBDA for (rsdp = (char *)0x00080000; // EBDA address (ulong)rsdp < (ulong)0x0009FFFF; // EBDA end rsdp++) { if (rsdp[0] == 'R' && rsdp[1] == 'S' && rsdp[2] == 'D' && rsdp[3] == ' ' && rsdp[4] == 'P' && rsdp[5] == 'T' && rsdp[6] == 'R' && rsdp[7] == ' ' ) { return (RSDPDescriptor *)rsdp; } } // Search in BDA for (rsdp = (char *)0x000E0000; // BDA address (ulong)rsdp < (ulong)0x000FFFFF; // BDA end rsdp++) { if (rsdp[0] == 'R' && rsdp[1] == 'S' && rsdp[2] == 'D' && rsdp[3] == ' ' && rsdp[4] == 'P' && rsdp[5] == 'T' && rsdp[6] == 'R' && rsdp[7] == ' ' ) { return (RSDPDescriptor *)rsdp; } } return NULL; } // // R/XSDT Exploration // static inline void IoInitRXSDT(void) { char checksum = 1; SDTHeader *rxsdt = AcpiSDT; // Map the Table Header for (ulong i = 0; i < (sizeof(SDTHeader)/KPAGESIZE) + 1; i++) { MmMapPage((void*)((ulong)(rxsdt) + i*KPAGESIZE), (void*)((ulong)(rxsdt) + i*KPAGESIZE), PRESENT); } // Checksum calculation checksum = DoChecksum(rxsdt, (size_t)rxsdt->length, 0, 0 ); if (checksum) KeStartPanic("Invalid RSDT checksum : %d vs 0", checksum); if (IoACPIVersion == 1) { KernLog("\tACPI Root System Table %s (%s) length %d [%p]\n", rxsdt->signature, rxsdt->OEMID, rxsdt->length, rxsdt ); } else { KernLog("\tACPI Extended System Table %s (%s) length %d [%p]\n", rxsdt->signature, rxsdt->OEMID, rxsdt->length, rxsdt ); } } // // RSDP Exploration // static inline void IoInitRSDP(void) { char checksum = 1; RSDPDescriptor *rsdp = IoFindRSDP(); if (!rsdp) KeStartPanic("ACPI RSDP not found in memory"); // Checksum calculation checksum = DoChecksum(rsdp, (size_t)sizeof(RSDPDescriptor), (size_t)sizeof(struct RSDPLegacy), !rsdp->legacy.revision ); if (checksum) KeStartPanic("Invalid RSDP checksum : %d vs 0", checksum); if (rsdp->legacy.revision == 1 || rsdp->legacy.revision >= 3) KeStartPanic("Invalid ACPI Revision : %d", rsdp->legacy.revision); KernLog("\tACPI Revision %d (OEM %s)\n", (uint)rsdp->legacy.revision, rsdp->legacy.OEMID ); AcpiSDT = (void *)(ulong)rsdp->legacy.rsdtAddress; if (rsdp->legacy.revision) { AcpiSDT = (void *)rsdp->xsdtAddress; IoACPIVersion = 2; } } // // Explore all ACPI Tables // static inline void IoSearchAcpiTables(void) { return; } // // Initialise the ACPI by finding tables // void IoInitAcpi(void) { if (BtFirmwareInfo.romValid) KernLog("\tRom Table is valid at %p\n", BtFirmwareInfo.romTable); if (BtFirmwareInfo.apmValid) KernLog("\tApm Table is valid at %p\n", BtFirmwareInfo.apmTable); // FIND RSDP IoInitRSDP(); IoInitRXSDT(); }