Skip to content
Henryk Paluch edited this page Dec 21, 2023 · 3 revisions

ACPI

WARNING!

ACPI is complex topic and I'm just barely touching surface... I apologise if there are any inaccuracies in this article...

ACPI is standard to enumerate hardware on PCs. Main use is to allow discovery of hardware that is not Plug and Play. It also plays central role on UEFI that is (unfortunately) replacing BIOS.

ACPI was first supposed to just replace (APM - Advanced Power Management). So Windows 2000 used it, for example, to power off machine after shutdown. However later it was vastly extended to also add hardware enumeration - similar purpose as DTS trees that are used to describe hardware on many Power and ARM machines, where often there is no BIOS nor UEFI, just some kind of loader that typically loads U-Boot from Flash and this later loads and runs Linux kernel.

However ACPI is complex topic which has unfortunate effect that even today there are many buggy implementations, (I remember that Windows 2000 rather completely ignored ACPI implementation before 1998, because they were mostly unusable).

How to dump ACPI

There is package acpica-tools or acpica that contains several ACPI utilities. Just found these slides:

And here is "ACPI Source Language" (ASL) Tutorial from Intel:

Install acpidump command:

# installation for Ubuntu 22.04 LTS:
sudo apt-get install acpica-tools
# installation for openSUSE LEAP 15.5
sudo zypper in acpica

How to dump ACPI tables as text/hexdump:

sudo acpidump

To just show table summaries (example for ZOTAC PC in BIOS mode - strangely there is even UEFI table)

# example for Zotac PC in BIOS mode:
sudo acpidump -s
ACPI: SSDT 0x0000000000000000 00072B (v02 CpuRef CpuSsdt  00003000 INTL 20120913)
ACPI: MCFG 0x0000000000000000 00003C (v01 ALASKA A M I    01072009 MSFT 00000097)
ACPI: APIC 0x0000000000000000 000084 (v03 INTEL  EDK2     00000003 BRXT 0100000D)
ACPI: SSDT 0x0000000000000000 0016E9 (v01 Intel_ Platform 00001000 INTL 20120913)
ACPI: NHLT 0x0000000000000000 001A50 (v00 INTEL  EDK2     00000002      01000013)
ACPI: UEFI 0x0000000000000000 000042 (v01 ALASKA A M I    00000000      00000000)
ACPI: DSDT 0x0000000000000000 007C5C (v02 ALASKA A M I    01072009 INTL 20120913)
ACPI: SSDT 0x0000000000000000 002760 (v02 SaSsdt SaSsdt   00003000 INTL 20120913)
ACPI: WSMT 0x0000000000000000 000028 (v00 INTEL  EDK2     00000003 BRXT 0100000D)
ACPI: LPIT 0x0000000000000000 00005C (v01 INTEL  EDK2     00000003 BRXT 0100000D)
ACPI: SSDT 0x0000000000000000 00032D (v02 PmRef  Cpu0Tst  00003000 INTL 20120913)
ACPI: DBG2 0x0000000000000000 000072 (v00 INTEL  EDK2     00000003 BRXT 0100000D)
ACPI: WDAT 0x0000000000000000 000104 (v01                 00000000      00000000)
ACPI: SSDT 0x0000000000000000 00039D (v02 PmRef  Cpu0Ist  00003000 INTL 20120913)
ACPI: DMAR 0x0000000000000000 0000A8 (v01 INTEL  EDK2     00000003 BRXT 0100000D)
ACPI: FACP 0x0000000000000000 000114 (v06 ALASKA A M I    01072009 AMI  00010013)
ACPI: FPDT 0x0000000000000000 000044 (v01 ALASKA A M I    01072009 AMI  00010013)
ACPI: SSDT 0x0000000000000000 000B53 (v02 INTEL  UsbCTabl 00000003 BRXT 0100000D)
ACPI: NPKT 0x0000000000000000 000065 (v01 INTEL  EDK2     00000003 BRXT 0100000D)
ACPI: MSDM 0x0000000000000000 000055 (v03 ALASKA A M I    01072009 AMI  00010013)
ACPI: PRAM 0x0000000000000000 000030 (v01 INTEL  EDK2     00000003 BRXT 0100000D)
ACPI: DBGP 0x0000000000000000 000034 (v01 INTEL  EDK2     00000003 BRXT 0100000D)
ACPI: HPET 0x0000000000000000 000038 (v01 INTEL  EDK2     00000003 BRXT 0100000D)
ACPI: SSDT 0x0000000000000000 00017C (v02 PmRef  ApTst    00003000 INTL 20120913)
ACPI: FIDT 0x0000000000000000 00009C (v01 ALASKA A M I    01072009 AMI  00010013)
ACPI: FACS 0x0000000000000000 000040
ACPI: SSDT 0x0000000000000000 00015F (v02 PmRef  ApIst    00003000 INTL 20120913)
ACPI: SSDT 0x0000000000000000 00008D (v02 PmRef  ApCst    00003000 INTL 20120913)
ACPI: SSDT 0x0000000000000000 000102 (v02 PmRef  Cpu0Cst  00003001 INTL 20120913)

How to dump ACPI files to binary .dat tables:

mkdir binary-tables
cd binary-tables
ls -1 *.dat | wc -l
# 29 dat files create for Zotac

You may ask what are those binary .dat for. It seems that they can be used for acpiexec command (rather do NOT run it as root) that contains ACPI interpreter. But I must admit that I don't understand it yet...

Here is little intro:

Here is other example:

# having *.dat files collected from Ubuntu 22.04 guest under Hyper-V 2012R2/UEFI (Gen2)
acpiexec -l *.dat
...
ACPI: RSDP 0x00005582BAE12120 000024 (v02 Intel )
ACPI: XSDT 0x00005582BBF3B4E0 00006C (v00 Intel  AcpiExec 00001001 INTL 20220331)
ACPI: FACP 0x00005582BBF3D550 0000F4 (v04 VRTUAL MICROSFT 00000001 MSFT 00000001)
ACPI: DSDT 0x00005582BBF3C790 000D8E (v02 MSFTVM DSDT01   00000001 MSFT 04000000)
ACPI: FACS 0x00005582BAE120E0 000040
ACPI: APIC 0x00005582BBF3C4F0 00024C (v02 VRTUAL MICROSFT 00000001 MSFT 00000001)
ACPI: BGRT 0x00005582BBF36D20 000038 (v01 INTEL  TIANO    00000001 MSFT 01000013)
ACPI: FACS 0x00005582BBF3D670 000040
ACPI: OEM0 0x00005582BBF3D6E0 000064 (v01 VRTUAL MICROSFT 00000001 MSFT 00000001)
ACPI: OEM1 0x00005582BBF3D770 00009E (v02 MSFTVM UARTS    00000001 MSFT 04000000)
ACPI: SRAT 0x00005582BBF3D840 000068 (v02 VRTUAL MICROSFT 00000001 MSFT 00000001)
ACPI: WAET 0x00005582BBF3D8D0 000028 (v01 VRTUAL MICROSFT 00000001 MSFT 00000001)
...
# enter "quit" to exit

How to decode content of specific table - using iasl

  • decompile binary .dat to .dsl, for example:
    iasl oem1.dat 
  • look into generated file - in my case oem1.dsl
    /*
     * Intel ACPI Component Architecture
     * AML/ASL+ Disassembler version 20220331 (64-bit version)
     * Copyright (c) 2000 - 2022 Intel Corporation
     * 
     * Disassembling to symbolic ASL+ operators
     *
     * Disassembly of oem1.dat, Tue Dec 19 17:44:02 2023
     *
     * Original Table Header:
     *     Signature        "OEM1"
     *     Length           0x0000009E (158)
     *     Revision         0x02
     *     Checksum         0x92
     *     OEM ID           "MSFTVM"
     *     OEM Table ID     "UARTS"
     *     OEM Revision     0x00000001 (1)
     *     Compiler ID      "MSFT"
     *     Compiler Version 0x04000000 (67108864)
     */
    DefinitionBlock ("", "OEM1", 2, "MSFTVM", "UARTS", 0x00000001)
    {
        Scope (_SB)
        {
            Device (UAR1)
            {
                Name (_HID, EisaId ("PNP0501") /* 16550A-compatible COM Serial Port */)  // _HID: Hardware ID
                Name (_DDN, "COM1")  // _DDN: DOS Device Name
                Name (_UID, One)  // _UID: Unique ID
                Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
                {
                    IRQ (Edge, ActiveHigh, Exclusive, )
                        {4}
                    IO (Decode16,
                        0x03F8,             // Range Minimum
                        0x03F8,             // Range Maximum
                        0x01,               // Alignment
                        0x08,               // Length
                        )
                })
            }
    
            Device (UAR2)
            {
                Name (_HID, EisaId ("PNP0501") /* 16550A-compatible COM Serial Port */)  // _HID: Hardware ID
                Name (_DDN, "COM2")  // _DDN: DOS Device Name
                Name (_UID, 0x02)  // _UID: Unique ID
                Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
                {
                    IRQ (Edge, ActiveHigh, Exclusive, )
                        {3}
                    IO (Decode16,
                        0x02F8,             // Range Minimum
                        0x02F8,             // Range Maximum
                        0x01,               // Alignment
                        0x08,               // Length
                        )
                })
            }
        }
    }
    

DSDT

DSDT is called Differentiated System Description Table (DSDT) and it is in center of my interest, because I have issues with OpenBSD kernel panicin in dsdt.c (which is likely to have issue).

Here is how to examine DSDT using acpiexec:

acpiexec dsdt.dat

- paths

ACPI Namespace (from root):
 1 Scope           _GPE
 2  Method         _GPE._E00
 1 Scope           _PR
 1 Device          _SB
 2  Method         _SB._INI
 2  Method         _SB.PSTA
...

# This one is printed before panic:

- d _SB._INI

Evaluating \_SB._INI
ArgObj:    0x557b13b023e0 <Node>            Name SCFG RegionField 0x557b13b027f0
ResultObj: 0x557b13b137a0 <Obj>             Integer 0000000000000000

00000/00A0: If (LGreater (SCFG, Zero)){}

- d _SB._INI
Evaluating \_SB._INI
ArgObj:    0x557b13b023e0 <Node>            Name SCFG RegionField 0x557b13b027f0
ResultObj: 0x557b13b137a0 <Obj>             Integer 0000000000000000

00000/00A0: If (LGreater (SCFG, Zero)){}

% 
ArgObj:    0x557b13b128d0 <Obj>             Integer 0000000000000000
ArgObj:    0x557b13b137a0 <Obj>             Integer 0000000000000000
ResultObj: 0x557b13b12800 <Obj>             Integer 0000000000000000

00000/00A0: If (Predicate = [False], Skipping IF block

% 
ArgObj:    0x557b13b024c0 <Node>            Name BFLG RegionField 0x557b13b028f0
ResultObj: 0x557b13b12800 <Obj>             Integer 0000000000000000

00025/00A0: If (And (BFLG, 0x02)){}

% 
ArgObj:    0x557b13b128d0 <Obj>             Integer 0000000000000000
ArgObj:    0x557b13b137a0 <Obj>             Integer 0000000000000002
ArgObj:    0x557b13b12800 <Obj>             Integer 0000000000000000
ResultObj: 0x557b13b139a0 <Obj>             Integer 0000000000000000

00025/00A0: If (Predicate = [False], Skipping IF block

% 
No object was returned from evaluation of \_SB._INI
- 

For comparison here is decompiled table - using iasl -lm dsdt.dat

  • it creates dsdt.map (empty in my case)
  • and dsdt.dsl

The begining of dsdt.dsl is familiar:

DefinitionBlock ("", "DSDT", 2, "MSFTVM", "DSDT01", 0x00000001)
{
    Scope (_SB)
    {
        Method (_INI, 0, NotSerialized)  // _INI: Initialize
        {
            If ((SCFG > Zero))
            {
                LoadTable ("OEM1", "MSFTVM", "UARTS", "\\", "", Zero)
            }

            If ((BFLG & 0x02))
            {
                LoadTable ("OEMP", "MSFTVM", "SPCI", "\\", "", Zero)
            }
        }
    }
....

Resources

Currently studying:

Clone this wiki locally