12using namespace MaxOS::hardwarecommunication;
13using namespace MaxOS::system;
14using namespace MaxOS::memory;
15using namespace MaxOS::common;
29 ASSERT(multiboot->
new_acpi() !=
nullptr || multiboot->
old_acpi() !=
nullptr,
"No ACPI found!");
32 m_using_new_acpi = multiboot->
old_acpi() ==
nullptr;
33 Logger::DEBUG() <<
"CPU Supports " << (m_using_new_acpi ?
"New" :
"Old") <<
" ACPI\n";
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
49 m_xsdt = (
XSDT*) virtual_address;
51 m_rsdt = (
RSDT*) virtual_address;
55 map_tables(m_using_new_acpi ?
sizeof(uint64_t) :
sizeof(uint32_t));
58 ASSERT(valid_checksum(),
"ACPI: Invalid checksum!");
61AdvancedConfigurationAndPowerInterface::~AdvancedConfigurationAndPowerInterface() =
default;
68void AdvancedConfigurationAndPowerInterface::map_tables(uint8_t pointer_size) {
70 size_t entries = (m_header->length -
sizeof(
ACPISDTHeader)) / pointer_size;
71 for(uint32_t i = 0; i < entries; i++) {
74 auto address = (uint64_t) (m_using_new_acpi ? m_xsdt->
pointers[i] : get_rsdt_pointer(i));
86virtual_address_t* AdvancedConfigurationAndPowerInterface::map_descriptor(uint64_t physical_address) {
90 uint64_t offset = physical_address - page;
98 m_header = (
ACPISDTHeader*) ((uint8_t*) virtual_address + offset);
99 ASSERT(m_header->length >=
sizeof(
ACPISDTHeader),
"ACPI table too short");
102 uint64_t end = page + m_header->length - 1;
106 for(uint64_t page_i = page + PAGE_SIZE; page_i <= end; page_i +=
PAGE_SIZE) {
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);
129 ASSERT(offset +
sizeof(uint32_t) <= m_header->length,
"RSDT index out of bounds");
133 memcpy(&value, raw + offset,
sizeof(uint32_t));
144bool AdvancedConfigurationAndPowerInterface::validate(
const char* descriptor,
size_t length) {
150 for(uint32_t i = 0; i < length; i++)
151 sum += ((
char*) descriptor)[i];
154 return ((sum & 0xFF) == 0);
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);
170 for(
size_t i = 0; i < entries; ++i) {
179 if(strncmp(header->signature, signature, 4))
192bool AdvancedConfigurationAndPowerInterface::valid_checksum() {
195 char* check = m_using_new_acpi ? (
char*) m_rsdp2 : (char*) m_rsdp;
200 for(uint32_t i = 0; i < length; i++)
Defines an Advanced Configuration And Power Interface (ACPI class for handling ACPI table parsing and...
static LogRecord DEBUG()
Gets the active logger for debug logs.
static LogRecord INFO()
Gets the active logger for info logs.
acpi_sdt_header_t * find(const char *signature)
Finds a table with the given signature.
AdvancedConfigurationAndPowerInterface(system::Multiboot *multiboot)
Construct a new Advanced Configuration And Power Interface object. Maps the ACPI headers and tables i...
static size_t align_direct_to_page(size_t size)
Aligns a address to the page size.
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...
void reserve(uint64_t address)
Reserves a physical address.
virtual_address_t * map(virtual_address_t *virtual_address, size_t flags)
Allocates a physical address to a virtual address.
static PhysicalMemoryManager * s_current_manager
The current physical memory manager in use.
Parses and provides access to Multiboot 2 information.
multiboot_tag_old_acpi * old_acpi()
Get the old ACPI tag.
multiboot_tag_new_acpi * new_acpi()
Get the new ACPI tag.
Defines a Logger class for logging messages with different severity levels to multiple output streams...
void virtual_address_t
A type representing a virtual address (used for readability)
void physical_address_t
A type representing a physical address (used for readability)
constexpr uint64_t PAGE_SIZE
The size of a page (4KB)
Root System Description Pointer (RSDP) structure for ACPI 2 and above.
Root System Description Pointer (RSDP) structure for ACPI 1.
Root System Description Table (RSDT) structure for ACPI 1. Contains the header and an array of pointe...
Extended System Description Table (XSDT) structure for ACPI 2 and above. Contains the header and an a...
uint64_t pointers[]
An array of physical addresses pointing to other ACPI SDTs.