Max OS 0.3
Loading...
Searching...
No Matches
acpi.cpp
Go to the documentation of this file.
1
9#include <common/logger.h>
10
11using namespace MaxOS;
12using namespace MaxOS::hardwarecommunication;
13using namespace MaxOS::system;
14using namespace MaxOS::memory;
15using namespace MaxOS::common;
16
24: m_header(nullptr) {
25
26 Logger::INFO() << "Setting up ACPI\n";
27
28 // If the new ACPI is not supported, panic
29 ASSERT(multiboot->new_acpi() != nullptr || multiboot->old_acpi() != nullptr, "No ACPI found!");
30
31 // Check if the new ACPI is supported
32 m_using_new_acpi = multiboot->old_acpi() == nullptr;
33 Logger::DEBUG() << "CPU Supports " << (m_using_new_acpi ? "New" : "Old") << " ACPI\n";
34
35 if(m_using_new_acpi)
36 m_rsdp2 = (RSDPDescriptor2*) (multiboot->new_acpi() + 1);
37 else
38 m_rsdp = (RSDPDescriptor*) (multiboot->old_acpi() + 1);
39
40 // Map the XSDT/RSDT
41 uint64_t physical_address = m_using_new_acpi ? m_rsdp2->xsdt_address : m_rsdp->rsdt_address;
42 void* virtual_address = map_descriptor(physical_address);
43 ASSERT(virtual_address != nullptr, "Failed to map ACPI table");
44 Logger::DEBUG() << "XSDT/RSDT: physical: 0x" << physical_address << ", virtual: 0x" << (uint64_t) virtual_address
45 << "\n";
46
47 // Load
48 if(m_using_new_acpi)
49 m_xsdt = (XSDT*) virtual_address;
50 else
51 m_rsdt = (RSDT*) virtual_address;
52
53 // Map the Tables
54 Logger::DEBUG() << "Mapping ACPI Tables\n";
55 map_tables(m_using_new_acpi ? sizeof(uint64_t) : sizeof(uint32_t));
56
57 // Check if the checksum is valid
58 ASSERT(valid_checksum(), "ACPI: Invalid checksum!");
59}
60
61AdvancedConfigurationAndPowerInterface::~AdvancedConfigurationAndPowerInterface() = default;
62
68void AdvancedConfigurationAndPowerInterface::map_tables(uint8_t pointer_size) {
69
70 size_t entries = (m_header->length - sizeof(ACPISDTHeader)) / pointer_size;
71 for(uint32_t i = 0; i < entries; i++) {
72
73 // Get the address (aligned to page)
74 auto address = (uint64_t) (m_using_new_acpi ? m_xsdt->pointers[i] : get_rsdt_pointer(i));
75 address = PhysicalMemoryManager::align_direct_to_page((size_t) address);
76
77 // Map to the higher half
79
80 // Reserve the memory
82 }
83
84}
85
86virtual_address_t* AdvancedConfigurationAndPowerInterface::map_descriptor(uint64_t physical_address) {
87
88 // Get the base page
90 uint64_t offset = physical_address - page;
91
92 // Map that page
94 PhysicalMemoryManager::s_current_manager->map((physical_address_t*) page, virtual_address, PRESENT | WRITE);
96
97 // Read the length
98 m_header = (ACPISDTHeader*) ((uint8_t*) virtual_address + offset);
99 ASSERT(m_header->length >= sizeof(ACPISDTHeader), "ACPI table too short");
100
101 // Where to stop looping
102 uint64_t end = page + m_header->length - 1;
104
105 // Map the remaining pages
106 for(uint64_t page_i = page + PAGE_SIZE; page_i <= end; page_i += PAGE_SIZE) {
108
111 }
112
113 return (void*) ((uint8_t*) PhysicalMemoryManager::to_io_region(page) + offset);
114}
115
124uint64_t AdvancedConfigurationAndPowerInterface::get_rsdt_pointer(size_t index) {
125 auto raw = (uint8_t*) m_rsdt;
126 size_t offset = sizeof(ACPISDTHeader) + index * sizeof(uint32_t);
127
128 // Ensure offset is within mapped header length (optional but safe)
129 ASSERT(offset + sizeof(uint32_t) <= m_header->length, "RSDT index out of bounds");
130
131 // Read the pointer manually
133 memcpy(&value, raw + offset, sizeof(uint32_t));
134 return value;
135}
136
144bool AdvancedConfigurationAndPowerInterface::validate(const char* descriptor, size_t length) {
145
146 // Checksum
147 uint32_t sum = 0;
148
149 // Calculate the checksum
150 for(uint32_t i = 0; i < length; i++)
151 sum += ((char*) descriptor)[i];
152
153 // Check if the checksum is valid
154 return ((sum & 0xFF) == 0);
155}
156
164
165 // Get the number of entries
166 size_t entries = (m_header->length - sizeof(ACPISDTHeader)) / sizeof(uint32_t);
167 if(m_using_new_acpi) entries = (m_header->length - sizeof(ACPISDTHeader)) / sizeof(uint64_t);
168
169 // Loop through all the entries
170 for(size_t i = 0; i < entries; ++i) {
171
172 // Get the entry
173 auto* header = (ACPISDTHeader*) (m_using_new_acpi ? m_xsdt->pointers[i] : get_rsdt_pointer(i));
174
175 // Move the header to the higher half
177
178 // Check if the signature matches
179 if(strncmp(header->signature, signature, 4))
180 return header;
181 }
182
183 // Return null if no entry was found
184 return nullptr;
185}
186
192bool AdvancedConfigurationAndPowerInterface::valid_checksum() {
193
194 // Get the information about the ACPI
195 char* check = m_using_new_acpi ? (char*) m_rsdp2 : (char*) m_rsdp;
196 uint32_t length = m_using_new_acpi ? sizeof(RSDPDescriptor2) : sizeof(RSDPDescriptor);
197
198 // Calculate the checksum
199 uint8_t sum = 0;
200 for(uint32_t i = 0; i < length; i++)
201 sum += check[i];
202
203 return sum == 0;
204}
Defines an Advanced Configuration And Power Interface (ACPI class for handling ACPI table parsing and...
static Logger DEBUG()
Gets active logger set to DEBUG level.
Definition logger.cpp:193
static Logger INFO()
Gets active logger set to info level.
Definition logger.cpp:171
Stores the left, top, width and height of a rectangle.
Definition rectangle.h:22
acpi_sdt_header_t * find(const char *signature)
Finds a table with the given signature.
Definition acpi.cpp:163
AdvancedConfigurationAndPowerInterface(system::Multiboot *multiboot)
Construct a new Advanced Configuration And Power Interface object. Maps the ACPI headers and tables i...
Definition acpi.cpp:23
static size_t align_direct_to_page(size_t size)
Aligns a address to the page size.
Definition physical.cpp:767
static void * to_io_region(uintptr_t physical_address)
Converts a physical address to an IO region address if it is in the lower region using the higher hal...
Definition physical.cpp:915
static PhysicalMemoryManager * s_current_manager
The current physical memory manager in use.
Definition physical.h:185
Parses and provides access to Multiboot 2 information.
Definition multiboot.h:518
Defines a Logger class for logging messages with different severity levels to multiple output streams...
#define ASSERT(condition, format,...)
If the specified condition is not met then the kernel will crash with the specified message.
Definition logger.h:100
void * memcpy(void *destination, const void *source, uint64_t num)
Copies a block of memory from one location to another.
Definition memoryIO.cpp:165
constexpr uint64_t PAGE_SIZE
The size of a page (4KB)
Definition physical.h:91
bool strncmp(char const *str1, char const *str2, int length)
Checks if one string pointer is equal to another string pointer up to a specified length (each must b...
Definition string.cpp:826
Common header for all ACPI System Description Tables (SDTs)
Definition acpi.h:59
Root System Description Pointer (RSDP) structure for ACPI 2 and above.
Definition acpi.h:44
Root System Description Pointer (RSDP) structure for ACPI 1.
Definition acpi.h:29
Root System Description Table (RSDT) structure for ACPI 1. Contains the header and an array of pointe...
Definition acpi.h:78
Extended System Description Table (XSDT) structure for ACPI 2 and above. Contains the header and an a...
Definition acpi.h:90
uint64_t pointers[]
An array of physical addresses pointing to other ACPI SDTs.
Definition acpi.h:92