Sunday 21 March 2010

Debugging ACPI using acpiexec

The acpiexec tool is an AML emulator that allows one to execute and interactively ACPI AML code from your BIOS.  The tarball can be downloaded from the ACPICA website  and built as follows:

1. Unzip and untar the acica-unix-20100304.tar.gz tarball.
2. cd into tools/acpiexec
3. run make

This should build acpiexec. Now for the fun part - executing your ACPI inside the emulator. To do this grab your ACPI tables and extract them using:
sudo acpidump > acpi.info && acpixtract -a acpi.info

Now load these tables into the emulator and run with verbose mode:

./acpiexec -v *.dat

Inside the emulator you can type help to navigate around the help system.  It may take a little bit of work to get familiar with all the commands available.

As a quick introduction, here is how to execute the battery information _BIF method.

1. Get a list of all the available methods, type:

methods

on my Lenovo laptop the battery information method is labelled \_SB_.PCI0.LPCB.BAT1._BIF, so to execute this method I use:

execute \_SB_.PCI0.LPCB.BAT1._BIF
Executing \_SB_.PCI0.LPCB.BAT1._BIF
Execution of \_SB_.PCI0.LPCB.BAT1._BIF returned object 0x19669d0 Buflen 178
  [Package] Contains 13 Elements:
    [Integer] = 0000000000000001
    [Integer] = 0000000000000FA0
    [Integer] = 0000000000000FA0
    [Integer] = 0000000000000001
    [Integer] = 0000000000002B5C
    [Integer] = 00000000000001A4
    [Integer] = 000000000000009C
    [Integer] = 0000000000000108
    [Integer] = 0000000000000EC4
    [String] Length 08 = PA3465U
    [String] Length 05 = 3658Q
    [String] Length 06 = Li-Ion
    [String] Length 07 = COMPAL

So far so good. I single stepped through the code using the debug command on the method as follows:

debug \_SB_.PCI0.LPCB.BAT1._BIF

at each % prompt, one can press enter to step the next instruction. If the method requires arguments, these can be passed into the method by specifying them after the method name from the debug command.

To see any local variables used during execution, use the locals command. The list command lists the current AML instructions. The set commands allows one to set method data and interact with the debugging processes.

Hopefully this gives one a taste of what the emulator can do. The internal help is enough to get one up and running, and one does generally require the current ACPI specification to figure out what's happening in your ACPI tables.

8 comments:

  1. Hi,

    Thanks for the info.
    Can you please be more specific/detailed about emulator part?
    I mean how to setup the emulator, what kind of emulator, etc?

    Thanks!

    ReplyDelete
  2. Err, it's quite easy to setup:

    1. Unzip and untar the acica-unix-20100304.tar.gz tarball.
    2. cd into tools/acpiexec/acpiexec
    3. run make

    ..not sure if I can expand on that much more.

    ReplyDelete
  3. Seems you didn't understand my question...

    I tough you run those in a qemu or something like that.

    After I fixed my DSDT(was a really mess and is replaced in BIOS) my computer boots only on Windows 7 or Linux, Vista or Xp panics complaining that BIOS is not ACPI compilant...

    So I'm looking for a way to debug it and find what is wrong...

    The DSDT was a really mess so no way to start over and test each modification(too many) rather I gave up on vista/xp.
    Tried both iasl and m$ compiler(latest as older versions) fixed some warnings on m$ one still no go :(
    So if you have any tip for me I would really appreciate.

    Thanks!

    ReplyDelete
  4. ..the acpiexec tool executes in emulation mode the AML, so it's all done inside this tool - no need to use anything like QEMU.

    ReplyDelete
  5. Thank you very much, just an info for those wo do not have acpidump in their distro, download the pmtool package from https://lesswatts.org/projects/acpi/utilities.php

    ReplyDelete
    Replies
    1. Thanks for pointing that out Vincent.

      Delete
    2. Could you please specify a point for me?
      Although acpiexec is very valuable to list the whole namespace, I do not seem to really interact with the platform using it: if I try to execute a _DIS method it won't change the return value of the _STA of the same device.
      On the other hand if I do this from within the kernel (I add a call to acpi_evaluate_object() in drivers/acpi/button.c) I can in some cases modify the _STA return value from 1111 to 1101 for a COM port...
      Am I using acpiexec the right way??

      Delete
    3. acpiexec runs from user space and cannot access the hardware, so some controls that perform I/O operations or communicate with the firmware using SMIs won't work. This probably explains the behaviour you are seeing with _DIS not being able to disable a device.

      Delete