UACPI: Difference between revisions

From OSDev.wiki
Jump to navigation Jump to search
[unchecked revision][unchecked revision]
Content added Content deleted
No edit summary
Line 32: Line 32:


== Initialization ==
== Initialization ==

Below is an example of basic uACPI initialization sequence that enters ACPI mode, parses tables, brings the event system online, and finally loads & initializes the namespace.

<source lang="c">
#include <uacpi/uacpi.h>

int acpi_init(uacpi_phys_addr rsdp_phys_addr) {
/*
* Set up the initialization parameters structure that configures uACPI
* behavior both at bring up and during runtime.
*/
uacpi_init_params init_params = {
/*
* Physical address of the RSDP structure that we have either found
* ourselves manually by scanning memory or (ideally) provided to us by
* the bootloader.
*/
.rsdp = rsdp_phys_addr,

/*
* Set up the runtime parameters, such as log level or behavior flags.
*/
.rt_params = {
/*
* Set the log level to TRACE, this is a bit verbose but perhaps
* okay for now since we're just getting started. We can change this
* to INFO later on, which is the recommended level for release
* builds. There's also the loudest UACPI_LOG_DEBUG log level, which
* is recommended to pin down lockups or hangs.
*/
.log_level = UACPI_LOG_TRACE,

/*
* Don't set any behavior flags, the defaults should work on most
* hardware.
*/
.flags = 0,
},
};

/*
* Proceed to the first step of the initialization. This loads all tables,
* brings the event subsystem online, and enters ACPI mode.
*/
uacpi_status ret = uacpi_initialize(&init_params);
if (uacpi_unlikely_error(ret)) {
log_error("uacpi_initialize error: %s", uacpi_status_to_string(ret));
return -ENODEV;
}

/*
* Load the AML namespace. This feeds DSDT and all SSDTs to the interpreter
* for execution.
*/
ret = uacpi_namespace_load();
if (uacpi_unlikely_error(ret)) {
log_error("uacpi_namespace_load error: %s", uacpi_status_to_string(ret));
return -ENODEV;
}

/*
* Initialize the namespace. This calls all necessary _STA/_INI AML methods,
* as well as _REG for registered operation region handlers.
*/
ret = uacpi_namespace_initialize();
if (uacpi_unlikely_error(ret)) {
log_error("uacpi_namespace_initialize error: %s", uacpi_status_to_string(ret));
return -ENODEV;
}
return 0;
}
</source>



== Example usage ==
== Example usage ==

Revision as of 19:24, 23 April 2024

ACPI
Fixed Tables
Differentiated Tables
Tools/Libs

uACPI is a portable and easy-to-integrate implementation of the Advanced Configuration and Power Interface (ACPI).

Its main focuses are full NT compatibility, safety, and minimization of stack usage by avoiding recursion entirely.

Extra documentation can be found in the project's GitHub repo.

Features

  • A complete & well-tested AML interpreter
  • Operation region subsystem, support for user-defined address space handlers & builtin handlers for SystemMemory/SystemIO/PCI_Config/TableData
  • User-defined device notify handlers & dispatch
  • A complete resource subsystem. Every resource defined by ACPI 6.5 (last release) is supported
  • Sleep API, allowing reset, transition to any sleep state, wake vector programming API
  • An advanced event subsystem, supporting GPE/fixed events, wake, implicit notify, AML handlers
  • PCI routing table retrieval & interrupt model API
  • Device search API

uACPI has been tested and confirmed to work on many real computers, both new and old, desktops and laptops. It has also been extensively fuzzed against both real world AML blobs & its own test suite.

The test suite runs on every commit and tests multiple types of configuration, including 64 and 32 bit builds on Windows (MSVC), Linux (GCC) and MacOS (AppleClang).

Why use uACPI if ACPICA is a thing?

This is discussed in great detail in the project's README.

Integrating into a kernel

Refer to the project's README for detailed instructions on how to do it.

Initialization

Below is an example of basic uACPI initialization sequence that enters ACPI mode, parses tables, brings the event system online, and finally loads & initializes the namespace.

#include <uacpi/uacpi.h>

int acpi_init(uacpi_phys_addr rsdp_phys_addr) {
    /*
     * Set up the initialization parameters structure that configures uACPI
     * behavior both at bring up and during runtime.
     */
    uacpi_init_params init_params = {
        /*
         * Physical address of the RSDP structure that we have either found
         * ourselves manually by scanning memory or (ideally) provided to us by
         * the bootloader.
         */
        .rsdp = rsdp_phys_addr,

        /*
         * Set up the runtime parameters, such as log level or behavior flags.
         */
        .rt_params = {
            /*
             * Set the log level to TRACE, this is a bit verbose but perhaps
             * okay for now since we're just getting started. We can change this
             * to INFO later on, which is the recommended level for release
             * builds. There's also the loudest UACPI_LOG_DEBUG log level, which
             * is recommended to pin down lockups or hangs.
             */
            .log_level = UACPI_LOG_TRACE,

            /*
             * Don't set any behavior flags, the defaults should work on most
             * hardware.
             */
            .flags = 0,
        },
    };

    /*
     * Proceed to the first step of the initialization. This loads all tables,
     * brings the event subsystem online, and enters ACPI mode.
     */
    uacpi_status ret = uacpi_initialize(&init_params);
    if (uacpi_unlikely_error(ret)) {
        log_error("uacpi_initialize error: %s", uacpi_status_to_string(ret));
        return -ENODEV;
    }

    /*
     * Load the AML namespace. This feeds DSDT and all SSDTs to the interpreter
     * for execution.
     */
    ret = uacpi_namespace_load();
    if (uacpi_unlikely_error(ret)) {
        log_error("uacpi_namespace_load error: %s", uacpi_status_to_string(ret));
        return -ENODEV;
    }

    /*
     * Initialize the namespace. This calls all necessary _STA/_INI AML methods,
     * as well as _REG for registered operation region handlers.
     */
    ret = uacpi_namespace_initialize();
    if (uacpi_unlikely_error(ret)) {
        log_error("uacpi_namespace_initialize error: %s", uacpi_status_to_string(ret));
        return -ENODEV;
    }
    
    return 0;
}


Example usage