DEV Community

moonlitpath
moonlitpath

Posted on

How Linux Figures Out What Hardware You Have

Why I wanted to explore:
In my previous post about forming a hypothesis about my Laptop's Blank screen issue, I had realized that my bug may not be a software bug, and instead be firmware or BIOS level. So, I went down this rabbit hole.


ACPI - Advanced Configuration and Power Interface Tables

What it is:

  • Describe how the OS should configure and control hardware
  • allows OS to manage power, devices and system configuration
  • stuff like--

    • CPU Power States
    • Sleep Modes
    • Device enumeration
    • Thermal Management
    • Interrupt Routing
  • Defined by BIOS/UEFI

Characteristics:

  • Dynamic hardware configuration
  • Contains AML byte-code interpreted by OS
  • Controls Power Management and device setup

ACPI is mainly used on PC platforms (esp x86 systems) to describe hardware configuration and enable operating system power management.

Other embedded systems (especially ARM-based systems) like phones and embedded boards use Device Trees.
Device Trees are simpler and mostly static hardware descriptions. They are not written in AML like ACPI. Instead they just describe the hardware layout -- devices, memory addresses, interrupts, buses, etc..
The OS reads the Device Tree during boot to figure out what hardware exists and how to access it. The kernel then uses this information to initialize devices and bind the appropriate drivers.


How the OS finds the ACPI table -- RSDP and XSDT

1) Finds RSDP

  • RSDP - Root System Description Pointer
  • this is the entry point to ACPI
  • OS gets it from UEFI config table, or in well known memory locations
  • also gets XSDT from here

2) Load XSDT

  • XSDT - Extended System Description Table
  • Contains list of pointers to other ACPI tables
XSDT
 ├── FADT
 ├── DSDT
 ├── SSDT
 ├── MADT
 ├── HPET
 └── others
Enter fullscreen mode Exit fullscreen mode
  • each entry is a 64 bit address pointing to another ACPI table

3) Parse Important tables
OS loads important tables for hardware initialization

Table Purpose
DSDT AML code describing devices
SSDT Additional AML definitions
MADT Interrupt controller (APIC)
FADT Power management
HPET High precision timer
SRAT NUMA topology

Then it parses AML bytecode, builds an internal device model, initializes power management


Logs from dmesg

observe the RSDP, XSDT, etc detection process shown here
we can clearly see how all tables were detected one by one during boot

[    0.007866] ACPI: Early table checksum verification disabled
[    0.007869] ACPI: RSDP 0x000000006D0B0014 000024 (v02 HPQOEM)
[    0.007872] ACPI: XSDT 0x000000006D0AF728 00010C (v01 HPQOEM SLIC-MPC 01072009 AMI  01000013)
[    0.007877] ACPI: FACP 0x000000006D0AA000 000114 (v06 HPQOEM SLIC-MPC 01072009 HP   00010013)
[    0.007881] ACPI: DSDT 0x000000006D056000 05308D (v02 HPQOEM 87FE     01072009 ACPI 20191018)
[    0.007883] ACPI: FACS 0x000000006D169000 000040
[    0.007885] ACPI: MCFG 0x000000006D0AE000 00003C (v01 HPQOEM 87FE     01072009 HP   00000097)
[    0.007887] ACPI: SSDT 0x000000006D0AB000 0025CF (v02 HPQOEM 87FE     00003000 ACPI 20191018)
[    0.007889] ACPI: FIDT 0x000000006D055000 00009C (v01 HPQOEM 87FE     01072009 HP   00010013)
[    0.007891] ACPI: MSDM 0x000000006D054000 000055 (v03 HPQOEM SLIC-MPC 00000001 HP   00010013)
[    0.007892] ACPI: SSDT 0x000000006D050000 0032D3 (v02 HPQOEM 87FE     00001000 ACPI 20191018)
[    0.007894] ACPI: SSDT 0x000000006D04D000 002B59 (v02 SaSsdt SaSsdt   00003000 INTL 20191018)
[    0.007896] ACPI: SSDT 0x000000006D049000 003350 (v02 HPQOEM 87FE     00003000 ACPI 20191018)
[    0.007898] ACPI: HPET 0x000000006D048000 000038 (v01 HPQOEM 87FE     01072009 HP   01000013)
[    0.007900] ACPI: APIC 0x000000006D047000 00012C (v04 HPQOEM 87FE     01072009 HP   01000013)
[    0.007902] ACPI: NHLT 0x000000006D046000 000F58 (v00 HPQOEM 87FE     01072009 HP   01000013)
[    0.007904] ACPI: LPIT 0x000000006D045000 0000CC (v01 HPQOEM 87FE     01072009 HP   01000013)
[    0.007906] ACPI: SSDT 0x000000006D041000 002720 (v02 HPQOEM 87FE     00001000 ACPI 20191018)
[    0.007908] ACPI: SSDT 0x000000006D040000 00012A (v02 HPQOEM 87FE     00000000 ACPI 20191018)
[    0.007910] ACPI: DBGP 0x000000006D03F000 000034 (v01 HPQOEM 87FE     01072009 HP   01000013)
[    0.007911] ACPI: DBG2 0x000000006D03E000 000054 (v00 HPQOEM 87FE     01072009 HP   01000013)
[    0.007913] ACPI: SSDT 0x000000006D03D000 000BA3 (v02 HPQOEM 87FE     00001000 ACPI 20191018)
[    0.007915] ACPI: DMAR 0x000000006D03C000 000088 (v02 HPQOEM 87FE     00000002 HP   01000013)
[    0.007917] ACPI: SSDT 0x000000006D03B000 000694 (v02 HPQOEM 87FE     00000000 ACPI 20191018)
[    0.007919] ACPI: SSDT 0x000000006D03A000 000144 (v02 HPQOEM 87FE     00001000 ACPI 20191018)
[    0.007921] ACPI: SSDT 0x000000006D039000 00009D (v01 HPQOEM 87FE     00000001 ACPI 20191018)
[    0.007923] ACPI: SSDT 0x000000006D038000 000060 (v01 HPQOEM 87FE     00000001 ACPI 20191018)
[    0.007925] ACPI: UEFI 0x000000006D0D9000 00063A (v01 HPQOEM 87FE     00000000 HP   00000000)
[    0.007926] ACPI: UEFI 0x000000006D0D8000 00005C (v01 HPQOEM 87FE     00000000 HP   00000000)
[    0.007928] ACPI: TPM2 0x000000006D037000 00004C (v04 HPQOEM 87FE     00000001 HP   00000000)
[    0.007930] ACPI: PTDT 0x000000006D036000 000CFE (v00 HPQOEM 87FE     00000005 HP   0100000D)
[    0.007932] ACPI: WSMT 0x000000006D044000 000028 (v01 HPQOEM 87FE     01072009 HP   00010013)
[    0.007934] ACPI: FPDT 0x000000006D035000 000044 (v01 HPQOEM 87FE     01072009 HP   01000013)
[    0.007936] ACPI: BGRT 0x000000006D034000 000038 (v01 HPQOEM 87FE     01072009 HP   00010013)

Enter fullscreen mode Exit fullscreen mode

Viewing ACPI tables

ACPI tables are stored in /sys/firmware/acpi/tables

root@laptop:# ls /sys/firmware/acpi/tables
APIC  DBG2  DSDT     FACS  HPET  MSDM  SSDT1   SSDT2  SSDT5  SSDT8  UEFI1
BGRT  DBGP  dynamic  FIDT  LPIT  NHLT  SSDT10  SSDT3  SSDT6  SSDT9  UEFI2
data  DMAR  FACP     FPDT  MCFG  PTDT  SSDT11  SSDT4  SSDT7  TPM2   WSMT
Enter fullscreen mode Exit fullscreen mode

They are all binary AML files, so they are unreadable

Decoding ACPI tables

install acpica tools

sudo apt install acpica-tools
Enter fullscreen mode Exit fullscreen mode

go to your folder where you want to dump the tables and create a directory

then dump the tables

sudo acpidump -b
Enter fullscreen mode Exit fullscreen mode

this extracts ACPI tables into binary files:

root@laptop:/home/anu/anu/programming/systems_progg/acpi_dump# sudo acpidump -b
root@laptop:/home/anu/anu/programming/systems_progg/acpi_dump# ls
apic.dat  facp.dat  mcfg.dat    ssdt12.dat  ssdt18.dat  ssdt6.dat  uefi2.dat
bgrt.dat  facs.dat  msdm.dat    ssdt13.dat  ssdt1.dat   ssdt7.dat  wsmt.dat
dbg2.dat  fidt.dat  nhlt.dat    ssdt14.dat  ssdt2.dat   ssdt8.dat
dbgp.dat  fpdt.dat  ptdt.dat    ssdt15.dat  ssdt3.dat   ssdt9.dat
dmar.dat  hpet.dat  ssdt10.dat  ssdt16.dat  ssdt4.dat   tpm2.dat
dsdt.dat  lpit.dat  ssdt11.dat  ssdt17.dat  ssdt5.dat   uefi1.dat
Enter fullscreen mode Exit fullscreen mode

Decompile a table

here, I'm reading DSDT table

convert it to readable ACPI code

iasl -d dsdt.dat
Enter fullscreen mode Exit fullscreen mode

this produces dsdt.dsl

and you can open this in a text editor to or using less to see what's in it


SSDT files and what they contain

SSDT: Secondary System Description Table

  • additional AML code

Why many SSDT exist instead of 1 big DSDT?

  • Modularity: each subsystem -- own ACPI table
  • Dynamic loading: some ssdts are loaded only when the hardware exists (like an optional gpu present, etc)
  • Vendors can easily update one ssdt instead of big dsdt

The exact purpose of that SSDT depends on firmware

This is how my SSDTs likely look:

SSDT Likely purpose
SSDT1 CPU topology
SSDT2 CPU power states
SSDT3 PCI root bridges
SSDT4 USB
SSDT5 GPU
SSDT6 thermal
SSDT7+ vendor specific

Editing ACPI tables

You can't "edit" ACPI tables, you override the ACPI tables at boot. This is done when firmware has buggy ACPI configurations

Steps:
1) Dump ACPI tables (as mentioned above)

2) Decompile (as mentioned above)

3) Edit the table
open the file with text editor and edit the file as required.

⚠️Warning: Editing must be done carefully. ACPI is firmware level hardware control code. Bad edits can cause boot issues, fans stuck, thermal shutdowns, power issues, etc.

4) Recompile

   `iasl -tc dsdt.dsl`
Enter fullscreen mode Exit fullscreen mode

o/p---> dsdt.aml

5) Now you can override your ACPI table via initramfs

5.1. Move aml file to /lib/firmware/acpi/

sudo mkdir -p /lib/firmware/acpi
sudo cp dsdt.aml /lib/firmware/acpi/
Enter fullscreen mode Exit fullscreen mode

5.2. Rebuild initramfs

sudo update-initramfs -u
Enter fullscreen mode Exit fullscreen mode

5.3 Reboot
5.4 Verify
check dmesg

dmesg | grep -i acpi
Enter fullscreen mode Exit fullscreen mode

You should see smth like this ACPI: overriding DSDT


Next step:

  1. Explore ACPI -- SSDT tables for understanding current C state configuration to check for bug hiding there.
  2. Figuring out if i915 driver interaction with ACPI power states is related to my bug's location I don't know whether the answer lies there, but I will look.

Top comments (0)