/* ------------------------------------------- Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. ------------------------------------------- */ #include #include #include #include namespace Kernel { constexpr STATIC const auto kMinACPIVer = 1U; /// @brief Finds a descriptor table inside ACPI XSDT. ErrorOr ACPIFactoryInterface::Find(const Char* signature) { if (this->fRsdp) return ErrorOr{kErrorInvalidData}; if (!signature) return ErrorOr{-kErrorInvalidData}; if (*signature == 0) return ErrorOr{-kErrorInvalidData}; RSDP* rsp_ptr = reinterpret_cast(this->fRsdp); if (rsp_ptr->Revision < kMinACPIVer) return ErrorOr{-kErrorInvalidData}; RSDT* xsdt = reinterpret_cast(rsp_ptr->RsdtAddress); Int64 num = (xsdt->Length - sizeof(SDT)) / sizeof(Int64); /*** crucial to avoid underflows. */ if (num < 1) { /// stop here, we should have entries... ke_panic(RUNTIME_CHECK_ACPI); return ErrorOr{-kErrorInvalidData}; } this->fEntries = num; (Void)(kout << "ACPI: Number of entries: " << number(this->fEntries) << kendl); (Void)(kout << "ACPI: Revision: " << number(xsdt->Revision) << kendl); (Void)(kout << "ACPI: Signature: " << xsdt->Signature << kendl); (Void)(kout << "ACPI: Address of XSDT: " << hex_number((UIntPtr) xsdt) << kendl); const short cAcpiSignatureLength = 4; for (Size index = 0; index < this->fEntries; ++index) { SDT* sdt = reinterpret_cast(xsdt->AddressArr[index]); (Void)(kout << "ACPI: Checksum: " << number(sdt->Checksum) << kendl); (Void)(kout << "ACPI: Revision: " << number(sdt->Revision) << kendl); for (short signature_index = 0; signature_index < cAcpiSignatureLength; ++signature_index) { if (sdt->Signature[signature_index] != signature[signature_index]) break; if (signature_index == (cAcpiSignatureLength - 1)) { (Void)(kout << "ACPI: SDT Signature: " << sdt->Signature << kendl); (Void)(kout << "ACPI: SDT OEM ID: " << sdt->OemId << kendl); return ErrorOr(reinterpret_cast(xsdt->AddressArr[index])); } } } return ErrorOr{-kErrorInvalidData}; } /*** @brief Checksum on SDT header. @param checksum the header to checksum @param len the length of it. */ bool ACPIFactoryInterface::Checksum(const Char* checksum, SSizeT len) { if (len == 0 || !checksum) return false; Char chr = 0; for (SSizeT index = 0L; index < len; ++index) { chr += checksum[index]; } return chr == 0; } ErrorOr ACPIFactoryInterface::operator[](const Char* signature) { if (!signature) return ErrorOr{-kErrorInvalidData}; return this->Find(signature); } } // namespace Kernel