-
Notifications
You must be signed in to change notification settings - Fork 142
ACPI for Developers
please share your ACPI knowledge
ACPI is an abbreviation of Advanced Configuration and Power Interface. The standard can be found at http://acpi.info.
ACPI is defining states for the whole system and for each component independently.
System states are:
- G0 (S0) : system fully ON.
- G1 : sleeping. Several sub-levels are defined here:
- S1 : power on suspend.
- S2 : suspend to RAM
- S3 : standby
- S4 : hibernate
- G2 (S5) : Soft Off. System still listening to some events (keyboard, USB, network) in order to start if received.
- G3 (S6) : Mechanical OFF. Only CMOS is running.
Device states are:
- D0 : ON.
- D1, D2 : intermediate, depend on device. May not be present.
- D3 : OFF.
When a device is in the D0 state, it could exist Performance states for it, starting from P0 (fully powered) and until P16 when accurate.
There are also CPU states, but they're not interesting for us.
The language used to manage ACPI is called ASL (ACPI Source Language). This language is, as far as we know, only described by the ACPI specs. However, as Intel gives out the code of the interpreter/compiler, we maybe be able to understand the language this way.
The language is compiled into AML (ACPI Machine Language) in a lot of tables, some of them are specific to the computer. List of tables :
- RSDP (Root System Description Pointer)
- RSDT (Root System Description Table)
- DSDT (Differentiated System Description Table). This table contains the primary AML code for the system.
- XSDT (Extended System Description Table)
- FADT (Fixed ACPI Description Table, signature "FACP"). This table contains configuration information about the ACPI hardware and pointers to the FACS and DSDT tables.
- FACS (Firmware ACPI Control Structure). This table contains the OS-to-firmware interface including the firmware waking vector and the Global Lock.
- SBST (Smart Battery Table)
- ECDT (Embedded Controller Boot Resources Table)
- MADT (Multiple APIC Description Table)
- SRAT (System Resource Affinity Table)
- SLIT (System Locality Distance Information Table)
- SLIC (Software Licensing Description Table)
- SSDT (Secondary System Descriptor Tables). Contains additional AML code
- THRM (CPU Thermal)
(Note (ArchangeGabriel) : I will add infos on these tables in the future, and also explain how to get them)
The AML code is stored in the BIOS, so a BIOS upgrade could change it (and often does).
In ASL, there are two different things :
- Scopes : sort of path, root is _SB, childs are added like _SB.CHILD
- Objects : they are contained in a path, and they are referred exactly like scopes, e.g. _SB.PATH.OBJT. They could be of five types:
- Buffer : a group of n*8 8bit integer, e.g. {0x00, 0x01, 0x02, 0x03, 0xFC, 0xFD, 0xFE, 0xFF}
- Integer : didn't determined size actually, will do that ASAP, they are something like 0xFFFFFFFFFFF.
- Bin : 0x00, 0x01, but also found as Zero, One.
- Function : a suit of instructions
- String : never seen any as of today
All of those things are having a name of maximum four latin caracters or _ (e.g. FUNC, VAR, but also _VAR, ...).
-
_REG
- initialize all Operation Regions -
_STA
,_INI
- initialize Device, Processor and Thermal objects. If there is no_INI
method,_STA
won't be considered -
_PRW
- identify and define GPEs (General Purpose Event) that are used for wake events (suspend etc?) -
_HID
- get hardware ID, "PNP0A03" is PCI Root Bridge, "PNP0A08" for PCI Express)
Resources:
- The ACPI spec is the most authoritative resource, the current version is 4.0a (released April 5, 2010; 731 pages)
- The ACPI Component Architecture
- ACPI implementation on FreeBSD
(Refer to Section 9.14.1: _DSM (Device Specific Method)) (Refer to Appendix A, Section 6: Display Device Class) (Refer to Appendix B: ACPI Extensions for Display Adapters)
What is interesting us here is theorically DSDT and SSDTs (there may be more than one SSDT table for a single computer), so we already started gathering those.
For now, we never see any card supporting D1 and D2. So, our goal here is to be able to switch between D0 and D3.
After analyzing some tables, there are some things to know :
- _ON and _OFF funcs should never be called as standalone. Some computers are having a better behavior here by integrating them at the right place directly or by checking some values before running them. We will call those two functions level 1 ones.
- What we need to call is _PS0 and _PS3. However, once again, these shouldn't be called as standalone. However, they look to have better stability/security mecanisms. We will call those functions level 2 ones. For example, we are actually sure that _PS3 ever requires to be run after a (correct) call to a certain _DSM function. This function would be the level 3 one.
- What we figured out: _DSM is called by some others functions, actually we saw two sets of such functions: WMMX on some Asus models, NVOP/NV3D for every others. Let's call those functions level 4 ones.
- Some functions require parameters, that is the case of DSM and method calling it. For DSM, args are generated by the function calling it, using its own args for that. But for those function, I'm guessing that we should use for argument some vars defined in the tables, as we can be pretty sure that they aren't here for nothing. But in order to do that, we need to reverse level 1 functions to understand what they do and what they need (actually, this seems useless, but to be sure, should be done), do the same for level 2 functions to understand what they need (and eventually what they do), reverse the level 3 function in order to understand what it does and what it expects as arguments in order to work, then reverse level 4 ones in order to understand what they do, how they generate args for level 3 one, and what are the expected args to do that.
- You must never try to set a device to a state it is already in !!! Normally, level 4 calls, if triggered as they should be, should be verifying that. Asking a card to go to D3 when already in could lead to crash, unability to use the card, ...
- We should power on the card before switching off or before going to sleep (for the computer, not you :P) because it can leads to some problems else.
ACPICA provides nice tools for working with this ACPI stuff. You may already have used iasl
or acpixtract
, but acpiexec
is another useful tool. Download the source from http://www.acpica.org/downloads/unix_source_code.php, extract it and run:
cd acpica-unix-*/tools/acpiexec
make
This will create the acpiexec
executable in the current directory. If you get an error like the below, edit the Makefile
file and remove the -Werror
flag from CWARNINGFLAGS
.
../../os_specific/service_layers/osunixxf.c:352:29: error: variable 'Count' set but not used [-Werror=unused-but-set-variable]
acpiexec
can be used for quickly getting all available methods, run acpiexec file.dat
where file.dat
is a DSDT or SSDT table generated by acpixtract
. Do not pass the disassembled file from iasl
, that won't work. After running something like acpiexec DSDT.dsl
, you can view all methods by running the methods
command. Run help
in the acpiexec
shell for more options.