diff --git a/bsps/x86_64/amd64/acpi/acpi.c b/bsps/x86_64/amd64/acpi/acpi.c index f7700b302f..efd16025c4 100644 --- a/bsps/x86_64/amd64/acpi/acpi.c +++ b/bsps/x86_64/amd64/acpi/acpi.c @@ -37,19 +37,57 @@ #include #include -#include #include uint64_t acpi_rsdp_addr = 0; +static bool acpi_tables_initialized = false; + +bool acpi_tables_initialize(void) +{ + ACPI_STATUS status; + + status = AcpiInitializeTables(NULL, ACPI_MAX_INIT_TABLES, FALSE); + + if (status == (AE_OK)) { + acpi_tables_initialized = true; + return true; + } + return false; +} + +void acpi_walk_subtables( + ACPI_TABLE_HEADER* table, + size_t size_of_header, + void (*handler)(ACPI_SUBTABLE_HEADER*) +) +{ + ACPI_SUBTABLE_HEADER* entry; + ACPI_SUBTABLE_HEADER* end; + + if (table == NULL) { + return; + } + + entry = (ACPI_SUBTABLE_HEADER*) ((uint8_t*) table + size_of_header); + end = (ACPI_SUBTABLE_HEADER*) ((uint8_t*) table + table->Length); + + while (entry < end) { + handler(entry); + entry = (ACPI_SUBTABLE_HEADER*) ((uint8_t*) entry + entry->Length); + } +} + static void initialize_acpi(void) { ACPI_STATUS status; status = AcpiInitializeSubsystem(); assert(status == (AE_OK)); - status = AcpiInitializeTables(NULL, ACPI_MAX_INIT_TABLES, FALSE); - assert(status == (AE_OK)); + if (acpi_tables_initialized == false) { + status = AcpiInitializeTables(NULL, ACPI_MAX_INIT_TABLES, FALSE); + assert(status == (AE_OK)); + } status = AcpiLoadTables(); assert(status == (AE_OK)); diff --git a/bsps/x86_64/amd64/include/acpi/acpi.h b/bsps/x86_64/amd64/include/acpi/acpi.h index 980d84a5e3..b288216dbb 100644 --- a/bsps/x86_64/amd64/include/acpi/acpi.h +++ b/bsps/x86_64/amd64/include/acpi/acpi.h @@ -39,9 +39,36 @@ #define _AMD64_ACPI_H_ #include +#include #define ACPI_MAX_INIT_TABLES 16 extern uint64_t acpi_rsdp_addr; +/** + * @brief Initializes the ACPICA Table Manager. Requires dynamic memory. + * + * The ACPICA Table Manager is independent of the rest of the ACPICA subsystem + * and only requires dynamic memory to be initialized (unless a statically + * allocated array for the tables is provided). Since access to ACPI tables + * may be required before the entire ACPICA subsystem can be initialized + * this routine can be used earlier in the system intialization. + * + * @return true if successful. + */ +bool acpi_tables_initialize(void); + +/** + * @brief Walks through the subtables of an ACPI table. + * + * @param table Pointer to the table. + * @param size_of_header Size of the table header (used to offset into first subtable). + * @param handler Handler that is called for each subtable found. + */ +void acpi_walk_subtables( + ACPI_TABLE_HEADER *table, + size_t size_of_header, + void (*handler)(ACPI_SUBTABLE_HEADER*) +); + #endif /* _AMD64_ACPI_H_ */