-
Notifications
You must be signed in to change notification settings - Fork 8
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).
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 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)
}
}
}
....
Currently studying:
- https://ubuntu.com/blog/debug-dsdt-ssdt-with-acpica-utilities
- https://ubuntu.com/blog/debug-acpi-tables-with-firmware-test-suite-fwts
- https://www.intel.com/content/www/us/en/developer/topic-technology/open/acpica/documentation.html
- https://cdrdv2-public.intel.com/772726/acpica-reference-19.pdf
- https://uefi.org/sites/default/files/resources/ACPI_Spec_6_4_A_final_Aug29.pdf
- https://uefi.org/sites/default/files/resources/ACPI_Spec_6_5_Aug29.pdf
- https://uefi.org/sites/default/files/resources/UEFI_Plugfest_May_2015%20-%20An%20Overview%20of%20ACPI%20Userspace%20Tools%20David%20Box%20Rev2.pdf
Copyright © Henryk Paluch. All rights reserved.
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License