summaryrefslogtreecommitdiffhomepage
path: root/dev/Kernel/src/ACPIFactoryInterface.cc
blob: cbfded4e1b0e7d18bb7f09005b1b600dad4aeb46 (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
89
90
91
92
93
94
95
96
/* -------------------------------------------

	Copyright (C) 2024, Amlal EL Mahrouss, all rights reserved.

------------------------------------------- */

#include <Mod/ACPI/ACPIFactoryInterface.h>
#include <NewKit/KString.h>
#include <ArchKit/ArchKit.h>
#include <KernelKit/Heap.h>

namespace Kernel
{
	/// @brief Finds a descriptor table inside ACPI XSDT.
	ErrorOr<voidPtr> ACPIFactoryInterface::Find(const Char* signature)
	{
		MUST_PASS(fRsdp);

		if (!signature)
			return ErrorOr<voidPtr>{-1};

		if (*signature == 0)
			return ErrorOr<voidPtr>{-1};

		RSDP* rsp_ptr = reinterpret_cast<RSDP*>(this->fRsdp);

		if (rsp_ptr->Revision <= 1)
			return ErrorOr<voidPtr>{-1};

		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>{-1};
		}

		this->fEntries = num;

		kcout << "ACPI: Number of entries: " << number(this->fEntries) << endl;
		kcout << "ACPI: Revision: " << number(xsdt->Revision) << endl;
		kcout << "ACPI: Signature: " << xsdt->Signature << endl;
		kcout << "ACPI: Address of XSDT: " << hex_number((UIntPtr)xsdt) << endl;

		const short cAcpiSignatureLength = 4;

		for (Size index = 0; index < this->fEntries; ++index)
		{
			SDT* sdt = reinterpret_cast<SDT*>(xsdt->AddressArr[index]);

			kcout << "ACPI: Checksum: " << number(sdt->Checksum) << endl;
			kcout << "ACPI: Revision: " << number(sdt->Revision) << endl;

			for (short signature_index = 0; signature_index < cAcpiSignatureLength; ++signature_index)
			{
				if (sdt->Signature[signature_index] != signature[signature_index])
					break;

				if (signature_index == (cAcpiSignatureLength - 1))
				{
					kcout << "ACPI: SDT Signature: " << sdt->Signature << endl;
					kcout << "ACPI: SDT OEM ID: " << sdt->OemId << endl;
					return ErrorOr<voidPtr>(reinterpret_cast<voidPtr>(xsdt->AddressArr[index]));
				}
			}
		}

		return ErrorOr<voidPtr>{-1};
	}

	/***
	@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)
			return 1;

		char chr = 0;

		for (int index = 0; index < len; ++index)
		{
			chr += checksum[index];
		}

		return chr == 0;
	}
} // namespace Kernel