blob: 42819b7eafaebfab7d03083efb5ca2c4a69ebdd2 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
/* ========================================
Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license.
======================================== */
#include <ArchKit/ArchKit.h>
#include <KernelKit/HeapMgr.h>
#include <NeKit/KString.h>
#include <modules/ACPI/ACPIFactoryInterface.h>
namespace Kernel {
constexpr STATIC const auto kMinACPIVer = 1U;
/// @brief Finds a descriptor table inside ACPI XSDT.
ErrorOr<voidPtr> ACPIFactoryInterface::Find(const Char* signature) {
if (this->fRsdp) return ErrorOr<voidPtr>{-kErrorInvalidData};
if (!signature) return ErrorOr<voidPtr>{-kErrorInvalidData};
if (*signature == 0) return ErrorOr<voidPtr>{-kErrorInvalidData};
RSDP* rsp_ptr = reinterpret_cast<RSDP*>(this->fRsdp);
if (rsp_ptr->Revision < kMinACPIVer) return ErrorOr<voidPtr>{-kErrorInvalidData};
RSDT* xsdt = reinterpret_cast<RSDT*>(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<voidPtr>{-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);
static constexpr const UInt16 cAcpiSignatureLength = 4U;
for (Size index = 0; index < this->fEntries; ++index) {
SDT* sdt = reinterpret_cast<SDT*>(xsdt->AddressArr[index]);
(Void)(kout << "ACPI: Checksum: " << number(sdt->Checksum) << kendl);
(Void)(kout << "ACPI: Revision: " << number(sdt->Revision) << kendl);
for (UInt16 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<voidPtr>(reinterpret_cast<voidPtr>(xsdt->AddressArr[index]));
}
}
}
return ErrorOr<voidPtr>{-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 NO;
Char chr = 0;
for (SSizeT index = 0L; index < len; ++index) {
chr += checksum[index];
}
return chr == 0;
}
ErrorOr<voidPtr> ACPIFactoryInterface::operator[](const Char* signature) {
if (!signature) return ErrorOr<voidPtr>{-kErrorInvalidData};
return this->Find(signature);
}
} // namespace Kernel
|