ACPI Tables
Recently I’ve had to work with querying some information from ACPI tables in Linux, to inspect some system parameters. This is the summary of what I have found out about what ACPI tables are, what information you can find in them and how to retrieve them.
In short, the ACPI tables are a collection of system parameters and information that is generated by firmware/BIOS (talking about x86 arch here). ACPI stands for Advanced Configuration and Power Interface, it is a specification and an industry standard for system firmware, to provide commonality in how certain parameters of the cpu and platform are reported to the Operating System. There are multiple tables defined by the standard , each one containing parameters about a specific system function or configuration.
How BIOS generates the tables is a topic that I don’t know much about, my intent here is to summarize how you can inspect the tables in a Linux OS and what type of information you can find in them.
Let’s take simple look at how you can use a linux application, named acpidump
to display the contents of the tables in hex format, acpidump can take different arguments and in the example below I use the signature
of a table to tell the application what I want to display. Each and every acpi table contains a distinctive signature
, which is a 4 uppercase character string. In the snippet below I’m telling acpidump to inspect the DMAR table, which contains information about the x86 IOMMU units enabled for the system. In the resulting dump I have modified some of the characters to x’s to avoid revealing some addresses which might be securiy sensitive.
$ sudo acpidump -n "DMAR"
DMAR @ 0x0000000000000000
0000: 44 4D 41 52 A0 00 00 00 02 AF 49 4E 54 45 4C 20 DMAR......INTEL
0010: 45 44 4B 32 20 20 20 20 02 00 00 00 20 20 20 20 EDK2 ....
0020: 13 00 00 01 26 05 00 00 00 00 00 00 00 00 00 00 ....&...........
0030: 00 00 18 00 00 00 00 00 xx xx xx xx xx xx xx xx ................
0040: 01 08 00 00 00 00 02 00 00 00 18 00 00 00 00 00 ................
0050: xx xx xx xx xx xx xx xx 02 08 00 00 00 00 07 00 .@..............
0060: 00 00 20 00 01 00 00 00 xx xx xx xx xx xx xx xx .. .............
0070: 03 08 00 00 02 00 1E 07 04 08 00 00 00 00 1E 06 ................
0080: 01 00 20 00 00 00 00 00 00 00 00 4C 00 00 00 00 .. ........L....
0090: FF FF 3F 50 00 00 00 00 01 08 00 00 00 00 02 00 ..?P............
How acpidump works is actually interesting and I had to go deep into the process of inspecting the ACPI table hirarchy and querying it to find the table of interest for me. It turns out that acpidump source code is part of the linux kernel, and it has had multiple versions. A particular version that I found interesting is the one on Linux kernel v3.14.34 where all acpi table location and inspection is done in userspace without the use of dedicated driver or kernel level api’s, from this source code you can tell that you can find the physical address base of the ACPI structrue in the /sys/firmware/efi/systab
path.
$ sudo cat /sys/firmware/efi/systab
ACPI20=0x<Address of RSDP>
ACPI=0x<concealed ;)>
SMBIOS3=<concealed ;)>
SMBIOS= <concealed ;)>
The acpidump app has an option to provide a physical address and it will try to interpret it as a table, but apparently, using the <Address of RSDP>
will only display the actual data if your kernel has been compiled with CONFIG_STRICT_DEVMEM
disabled. My running kernel doesn’t have this config disabled and I’m not going to compile a kernel just for this, so I will skip the screen capture. The traversal of the table hierarchy starts finding the RSD PTR
Root System Descriptor Pointer, the RSDP structure contains either a RsdtAddress
for 32bit base address or a XsdtAddress
for 64bit address. In turn, the Rsdt
or Xsdt
will contain a header and an array of physical addresses which are the base of other ACPI tables. To find the table of interest you would need to inspect the first 4 bytes at every physical address in the array looking for the signature that identifies the table.
Doing the ACPI tables inspection from user space is one possibility, but typically the information that is extracted from them is mostly useful to kernel and device drivers. The linux kernel does have APIs that are very easy to use to just retrieve the contents of the tables without caring about the details.
<linux src>/drivers/acpi/acpica/tbxface.c
FUNCTION: acpi_get_table
PARAMETERS: signature - ACPI signature of needed table
instance - Which instance (for SSDTs)
out_table - Where the pointer to the table is returned
RETURN: Status and pointer to the requested table
DESCRIPTION: Finds and verifies an ACPI table. Table must be in the
RSDT/XSDT.
Note that an early stage acpi_get_table() call must be paired
with an early stage acpi_put_table() call. otherwise the table
pointer mapped by the early stage mapping implementation may be
erroneously unmapped by the late stage unmapping implementation
in an acpi_put_table() invoked during the late stage.