Home

Awesome

uACPI

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

CI

[!WARNING] Not yet ready for production use! While the project is mostly feature-complete, it is still under active development. Public API may change, get added or removed without notice. Thread safety is currently lacking, see #74 for more info & progress.

Features

Why would I use this over ACPICA?

Whilst ACPICA is an old and battle-tested project, it still has some fundamental issues that make it very far from perfect or ideal.

TLDR:

More detailed overview

Expressions within package:

Method (TEST) {
    Local0 = 10
    Local1 = Package { Local0 * 5 }
    Return (DerefOf(Local1[0]))
}

// ACPICA: AE_SUPPORT, Expressions within package elements are not supported
// Windows, uACPI: Local0 = 50
Local0 = TEST()

Packages outside of a control method:

// ACPICA: internal error
// Windows, uACPI: ok
Local0 = Package { 1 }

Reference rebind semantics:

Local0 = 123
Local1 = RefOf(Local0)

// ACPICA: Local1 = 321, Local0 = 123
// Windows, uACPI: Local1 = reference->Local0, Local0 = 321
Local1 = 321

Increment/Decrement:

Local0 = 123
Local1 = RefOf(Local0)

// ACPICA: error
// Windows, uACPI: Local0 = 124
Local1++

Multilevel references:

Local0 = 123
Local1 = RefOf(Local0)
Local2 = RefOf(Local1)

// ACPICA: Local3 = reference->Local0
// Windows, uACPI: Local3 = 123
Local3 = DerefOf(Local2)

Implict-cast semantics:

Name (TEST, "BAR")

// ACPICA: TEST = "00000000004F4F46"
// Windows, uACPI: TEST = "FOO"
TEST = 0x4F4F46

Buffer size mutability:

Name (TEST, "XXXX")
Name (VAL, "")

// ACPICA: TEST = "LONGSTRING"
// Windows, UACPI: TEST = "LONG"
TEST = "LONGSTRING"

// ACPICA: VAL = "FOO"
// Windows, UACPI: VAL = ""
VAL = "FOO"

Returning a reference to a local object:

Method (TEST) {
    Local0 = 123

    // Use-after-free in ACPICA, perfectly fine in uACPI
    Return (RefOf(Local0))
}

Method (FOO) {
    Name (TEST, 123)

    // Use-after-free in ACPICA, object lifetime prolonged in uACPI (node is still removed from the namespace)
    Return (RefOf(TEST))
}

There's even more examples, but this should be enough to demonstrate the fundamental differences in designs.

Integrating into a kernel

1. Add uACPI sources & include directories into your project

If you're using CMake

Simply add the following lines to your cmake:

include(uacpi/uacpi.cmake)

target_sources(
    my-kernel
    PRIVATE
    ${UACPI_SOURCES}
)

target_include_directories(
    my-kernel
    PRIVATE
    ${UACPI_INCLUDES}
)

If you're using Meson

Add the following lines to your meson.build:

uacpi = subproject('uacpi')

uacpi_sources = uacpi.get_variable('sources')
my_kernel_sources += uacpi_sources

uacpi_includes = uacpi.get_variable('includes')
my_kernel_includes += uacpi_includes

Any other build system

2. Implement/override platform-specific headers

uACPI defines all platform/architecture-specific functionality in a few headers inside include/uacpi/platform

All of the headers can be "implemented" by your project in a few ways:

Currently used platform-specific headers are:

3. Implement kernel API

uACPI relies on kernel-specific API to do things like mapping/unmapping memory, writing/reading to/from IO, PCI config space, and many more things.

This API is declared in kernel_api.h and is implemented by your kernel.

4. Initialize uACPI

That's it, uACPI is now integrated into your project.

You should proceed to initialization.
Refer to the uACPI page on osdev wiki to see a snippet for basic initialization, as well as some code examples of how you may want to use certain APIs.

All of the headers and APIs defined in uacpi are public and may be utilized by your project.
Anything inside uacpi/internal is considered private/undocumented and unstable API.

Developing and contributing

Most development work is fully doable in userland using the test runner.

Setting up an IDE:

Simply open tests/runner/CMakeLists.txt in your favorite IDE.

For Visual Studio:

cd tests\runner && mkdir build && cd build && cmake ..

Then just simply open the .sln file generated by cmake.

Running the test suite:

./tests/run_tests.py

If you want to contribute:

All contributions are very welcome!

License

<a href="https://opensource.org/licenses/MIT"> <img align="right" height="96" alt="MIT License" src="https://branding.cute.engineering/licenses/mit.svg" /> </a>

uACPI is licensed under the MIT License.
The full license text is provided in the LICENSE file inside the root directory.