
Fixing Broken ACPI DSDT Tables on Linux
- 7 minsIn 2005 I ran into a broken DSDT on an HP Omnibook XE3 GF laptop. The BIOS advertised ACPI support, but Linux could not use it properly, and I ended up patching the table myself. This post was originally written in Italian as documentation of that work. It has been updated with current tooling.
The procedure is less awkward than it was. The work itself has not changed: extract the table, read it, correct the real errors, and load the override.
The symptom
dmidecode reported the BIOS as ACPI-capable:
BIOS Information
Vendor: Phoenix Technologies LTD
Version: GF.M1.14
...
ACPI Supported
The kernel, however, logged AML errors at bootstrap:
ACPI-0178: *** Warning: The ACPI AML in your computer contains errors,
please nag the manufacturer to correct it.
ACPI-0181: *** Warning: Allowing relaxed access to fields;
turn on CONFIG_ACPI_DEBUG for details.
The DSDT shipped with the BIOS contained errors, and Linux inherited them.
What the DSDT is
The DSDT (Differentiated System Description Table) is an ACPI table that describes devices, methods, and hardware regions to the operating system. In firmware it is stored as AML (ACPI Machine Language), a bytecode. The editable form, produced by decompiling the AML with iasl, is ASL (ACPI Source Language, commonly saved with a .dsl extension).
Errors in the DSDT propagate into Linux as broken power management, incorrect device behaviour, and thermal or battery misreporting. Fixing them means decompiling the AML, editing the ASL source, recompiling back to AML, and telling the kernel to load the corrected table instead of the one in the BIOS.
Procedure
The procedure always starts the same way: dump the table, decompile AML to DSL, modify the source, recompile.
Install the Intel ACPI compiler:
sudo apt install iasl # Debian/Ubuntu
sudo dnf install acpica-tools # Fedora/RHEL
sudo pacman -S acpica # Arch
sudo zypper install acpica # openSUSE
Extract the current DSDT. On modern Linux the sysfs interface is the simplest path:
sudo cp /sys/firmware/acpi/tables/DSDT dsdt.dat
Alternatively, with acpidump from acpica-tools:
sudo acpidump -b -n DSDT
The older /proc/acpi/dsdt entry has been removed from most recent kernels, so prefer one of the two above.
Decompile:
iasl -d dsdt.dat
This produces dsdt.dsl, the human-readable ASL source. Recompile it to see what the compiler flags:
iasl -tc dsdt.dsl
On the HP, the recompilation reported several errors:
dsdt.dsl 173: Method (_WAK, 1, NotSerialized)
Warning 2026 - Reserved method must return a value (_WAK)
dsdt.dsl 1443: SRST, 1,
Error 1051 - Access width of Field Unit extends beyond region limit
dsdt.dsl 2959: Field (ERAM, AnyAcc, Lock, preserve)
Error 1048 - Host Operation Region requires ByteAcc access
The fixes
In my case the errors fell into four categories.
_WAK missing return value
The _WAK method did not return the value required by the spec. Reserved methods must return a package:
Method (_WAK, 1, NotSerialized)
{
/* existing wake-up logic */
Return(Package(0x02){0x00, 0x00})
}
OperationRegion too small
An OperationRegion was declared with insufficient length, so a Field defined against it overran the region boundary. Extending the region by one byte resolved it:
OperationRegion (GPIO, SystemIO, 0x1180, 0x3C)
Field access type
A Field was declared with AnyAcc, which was incompatible with the host operation region. The region required ByteAcc:
Field (ERAM, ByteAcc, Lock, Preserve)
Unreachable code
A premature Return statement left code after it unreachable. Removing the early return put the trailing code back on the execution path.
Verification
After the corrections, the table compiled clean:
Compilation complete. 0 Errors, 0 Warnings, 0 Remarks, 482 Optimizations
Applying the override today
Applying a DSDT override on a current Linux system depends on two things: a kernel built with CONFIG_ACPI_TABLE_UPGRADE (enabled on most distribution kernels) and an initramfs that delivers the override AML to the kernel before it uses the firmware copy.
The kernel picks up the override from an early cpio archive prepended to the main initramfs, at the path kernel/firmware/acpi/dsdt.aml:
mkdir -p kernel/firmware/acpi
cp DSDT.aml kernel/firmware/acpi/
find kernel | cpio -H newc --create > acpi_override.img
The resulting acpi_override.img has to be prepended (not appended or merged) to the regular initramfs that the bootloader loads. The integration step varies across distributions, so the recipe on one system is not necessarily the recipe on another: check the ACPI override documentation for your distribution before running anything on a working install.
In 2005 the path was considerably more invasive. The override usually meant patching the kernel with a DSDT patch, editing an initrd by hand, and rebuilding the kernel on every change to the DSDT. LILO was still a common bootloader at the time.
When this still matters
A DSDT override is worth taking on when the problem is clearly in the firmware rather than in the driver. Common signs:
- Suspend and resume failures that survive driver updates
- Fans running at full speed regardless of thermal input
- Battery or AC state reported incorrectly
- Devices not appearing in the ACPI enumeration at all
The modern debugging tools are more usable than what was available in 2005:
# ACPI errors in the log
journalctl -b | grep -i acpi
# Dump the full set of ACPI tables
sudo acpidump -o acpi_tables.dat
acpixtract -a acpi_tables.dat
# Watch ACPI events in real time
sudo acpi_listen
# Available power states
cat /sys/power/state
Watch Out
A few things that can make DSDT fixes harder than they should be:
Secure Boot blocks unsigned DSDT overrides. On a UEFI system with Secure Boot enabled, a custom DSDT in initramfs will not load. The bootloader silently ignores it: no error, no warning, the fix just does not apply. Either disable Secure Boot or sign the initramfs with a Machine Owner Key (MOK).
Fixing one iasl error often exposes more. DSDT errors cascade. A single
Warning 2026cleared can uncover severalError 1051entries underneath. Fix, recompile, repeat.iasl version matters. A DSDT compiled with a newer iasl can produce different AML than the same source compiled with an older one. If the kernel was built expecting one version’s output, the other may cause subtle runtime issues. Match the iasl version to what the distribution ships, not the latest upstream release.
Hardware register addresses are real. When a DSDT contains
OperationRegion (GPIO, SystemIO, 0x1180, 0x3C), that0x1180maps to actual hardware. Changing it to silence a compile error can corrupt data or misbehave at the hardware level. Only modify register addresses with the chipset datasheet in front of you.Rebooting is mandatory. A DSDT override cannot be tested on a running system. Reloading ACPI kernel modules will not load a new table. The override only takes effect after reboot with the updated initramfs.
Closing
The tooling has improved, but the important part is still reading what the firmware is actually doing and correcting specific errors. Most DSDT problems are mundane: a missing return value, a region sized wrong by one byte, an access type that does not match its region.
If This Helped
Debugging ACPI tables is the kind of work that takes hours to figure out and minutes to apply. If this guide saved you that time, consider supporting the blog.
Most readers scroll past. Less than 3% of readers contribute to keeping independent technical content free and accessible.