ACPICA is an open-source project that provides an operating system (OS)-independent reference implementation. It also contains a list of utilities such as ASL compiler (iasl), acpiexec (an AML emulator). However, AML debugging on Linux in run-time wasn’t provided in ACPICA until Linux Kernel 4.13.
Enabling AML Debugging
The aml-debugger.txt is the instruction for enabling AML run-time debugger. This document is available at Documentation/acpi/ in Linux kernel source code. In short, two things are required for AML run-time debugging
- Enable AML debugging (CONFIG_ACPI_DEBUGGER=y & CONFIG_ACPI_DEBUGGER_USER=m) when compiling Linux kernel
- Compile an utility, acpidbg from Linux kernel (I uploaded a copy here)
While compiling a custom-build kernel is nothing new to kernel developers, it is often inconvenient for system firmware / BIOS developers. Fortunately, Ubuntu 18.04 (x64) and later enable these config by default. One can simply execute acpidbg on Ubuntu 18.04 – even on Ubuntu Live from USB too!
Running AML Debugging
Executing acpidbg on Ubuntu 18.04 (x64) is straight-forward
$ sudo ./acpidbg -
and “help” shows a list supported commands
- help General-Purpose Commands: ... ... Namespace Access Commands: ... ... Control Method Execution Commands: ... ...
acpidbg is particularly handy when one needs to evaluate any ACPI AML objects during run-time – especially ones that change under different conditions. This may be explained by some examples below:
Example 1 – To determine AC power status in run-time.
- Find _PSR objects
- Evaluate _PSR when AC is disconnected
- Evaluate _PSR when AC is connected
- find _PSR \_SB.PCI0.LPC.EC.AC._PSR Method 00000000c53d0a47 01 Args 0 Len 0023 Aml 00000000eab88cb2 - execute \_SB.PCI0.LPC.EC.AC._PSR Evaluating \_SB.PCI0.LPC.EC.AC._PSR Evaluation of \_SB.PCI0.LPC.EC.AC._PSR returned object 00000000c46fa555, external buffer length 18 [Integer] = 0000000000000000 - execute \_SB.PCI0.LPC.EC.AC._PSR Evaluating \_SB.PCI0.LPC.EC.AC._PSR Evaluation of \_SB.PCI0.LPC.EC.AC._PSR returned object 00000000c46fa555, external buffer length 18 [Integer] = 0000000000000001
acpidbg also works with complex objects such as packages.
- Find _BIF and _BST objects
- Evaluate _BIF and _BST objects (note _BST changes dynamically).
Example 2 – To determine battery information and status
- find _BIF \_SB.PCI0.LPC.EC.BAT0._BIF Method 00000000817541c3 01 Args 0 Len 0040 Aml 000000009abb252e - execute \_SB.PCI0.LPC.EC.BAT0._BIF Evaluating \_SB.PCI0.LPC.EC.BAT0._BIF Evaluation of \_SB.PCI0.LPC.EC.BAT0._BIF returned object 00000000c46fa555, external buffer length 170 [Package] Contains 13 Elements: [Integer] = 0000000000000000 [Integer] = 000000000000ABE0 [Integer] = 0000000000009E34 [Integer] = 0000000000000001 [Integer] = 0000000000003B60 [Integer] = 00000000000007E9 [Integer] = 00000000000000C8 [Integer] = 0000000000000001 [Integer] = 0000000000000001 [String] Length 07 = "00HW027" [String] Length 05 = " 409" [String] Length 03 = "LiP" [String] Length 03 = "SMP" - find _BST \_SB.PCI0.LPC.EC.BAT0._BST Method 00000000ed98c5ba 01 Args 0 Len 001D Aml 00000000a48eaeb6 - execute \_SB.PCI0.LPC.EC.BAT0._BST Evaluating \_SB.PCI0.LPC.EC.BAT0._BST Evaluation of \_SB.PCI0.LPC.EC.BAT0._BST returned object 00000000c46fa555, external buffer length 78 [Package] Contains 4 Elements: [Integer] = 0000000000000001 [Integer] = 00000000000010C6 [Integer] = 00000000000088B8 [Integer] = 0000000000003FC9
acpidbg can decode bit fields and save time on counting bits. Try to run acpidbg to evaluate any _PLD objects and you will see what I mean :).