ACPI Errors Fixing

An example how to fix the following ACPI errors experienced on some of HP notebooks.
$ dmesg | grep 'ACPI Error'
[    8.397813] ACPI Error: [CFGD] Namespace lookup failure, AE_NOT_FOUND (20160831/psargs-359)
[    8.398670] ACPI Error: Method parse/execution failed [\_TZ.PSL] (Node ffff88048d0a8d20), AE_NOT_FOUND (20160831/psparse-543)
[    8.399741] ACPI Error: Method parse/execution failed [\_TZ.GFXZ._PSL] (Node ffff88048d0a8190), AE_NOT_FOUND (20160831/psparse-543)
[    9.119569] ACPI Error: [CFGD] Namespace lookup failure, AE_NOT_FOUND (20160831/psargs-359)
[    9.120266] ACPI Error: Method parse/execution failed [\_TZ.PSL] (Node ffff88048d0a8d20), AE_NOT_FOUND (20160831/psparse-543)
[    9.121184] ACPI Error: Method parse/execution failed [\_TZ.BATZ._PSL] (Node ffff88048d0a8a50), AE_NOT_FOUND (20160831/psparse-543)
  1. Install iasl package.
  2. Create a directory to which ACPI tables can be extracted and decompiled:
    mkdir ~/acpi
    cd ~/acpi
    acpidump > acpidump
    acpixtract acpidump
    iasl -e ssdt*.dat -d dsdt.dat
    
  3. Examine DSDT and related SSDT tables if necessary. Observe the hierarchy of the structures to properly locate the problematic code. Noting ACPI names consist of up to four letters and can repeat multiple times among the namespaces. Please see ACPICA Documentation for more.
  4. In the above mentioned case it turned out that \_TZ.GFXZ._PSL and \_TZ.BATZ._PSL methods call \_TZ.PSL method which fails because of not recognized CFGD object. It seems that the purpose of the last mentioned method is to return number of installed CPU cores. The fix consists of modifying dsdt.dsl file, removing the problematic code and increasing OEM revision.

    Before:

    DefinitionBlock ("", "DSDT", 2, "HPQOEM", "1909    ", 0x00000001)
    ...
            Method (PSL, 0, Serialized)
            {
                If ((CFGD & 0x01000000))
                {
                    If ((TCNT == 0x08))
                    {
                        Return (Package (0x08)
                        {
                            \_PR.CPU0, 
                            \_PR.CPU1, 
                            \_PR.CPU2, 
                            \_PR.CPU3, 
                            \_PR.CPU4, 
                            \_PR.CPU5, 
                            \_PR.CPU6, 
                            \_PR.CPU7
                        })
                    }
    
                    If ((TCNT == 0x04))
                    {
                        Return (Package (0x04)
                        {
                            \_PR.CPU0, 
                            \_PR.CPU1, 
                            \_PR.CPU2, 
                            \_PR.CPU3
                        })
                    }
    
                    Return (Package (0x02)
                    {
                        \_PR.CPU0, 
                        \_PR.CPU1
                    })
                }
                Else
                {
                    Return (Package (0x01)
                    {
                        \_PR.CPU0
                    })
                }
            }
    

    After:

    DefinitionBlock ("", "DSDT", 2, "HPQOEM", "1909    ", 0x00000002)
    ...
            Method (PSL, 0, Serialized)
            {
                    If ((TCNT == 0x08))
                    {
                        Return (Package (0x08)
                        {
                            \_PR.CPU0, 
                            \_PR.CPU1, 
                            \_PR.CPU2, 
                            \_PR.CPU3, 
                            \_PR.CPU4, 
                            \_PR.CPU5, 
                            \_PR.CPU6, 
                            \_PR.CPU7
                        })
                    }
    
                    If ((TCNT == 0x04))
                    {
                        Return (Package (0x04)
                        {
                            \_PR.CPU0, 
                            \_PR.CPU1, 
                            \_PR.CPU2, 
                            \_PR.CPU3
                        })
                    }
    
                    Return (Package (0x02)
                    {
                        \_PR.CPU0, 
                        \_PR.CPU1
                    })
            }
    

    Just in case here is the diff:

  5. Compile the file and create CPIO archive from it which will be used as an initial ramdisk to override the original ACPI table during the kernel boot. Please see DSDT - ArchWiki and Upgrading ACPI tables via initrd for more:
    mkdir -p kernel/firmware/acpi
    iasl -tc dsdt.dsl
    cp dsdt.aml kernel/firmware/acpi
    find kernel | cpio -H newc --create > /boot/acpi_override
    
  6. Edit the boot loader configuration file to include the ramdisk as one of the first ones. For example in case of Arch Linux GRUB2 modify /boot/grub/grub.cfg file to contain the following section for the active kernel:
    initrd /boot/intel-ucode.img /boot/acpi_override /boot/initramfs-linux.img
    
  7. Reboot the system to apply the ACPI fix and verify ACPI table override works and there are no ACPI errors:
    $ dmesg | grep -e 'ACPI Error' -e 'ACPI: DSDT' -e 'ACPI: Table'
    [    0.000000] ACPI: DSDT ACPI table found in initrd [kernel/firmware/acpi/dsdt.aml][0x23eef]
    [    0.000000] ACPI: Table Upgrade: override [DSDT-HPQOEM-1909    ]
    [    0.000000] ACPI: DSDT 0x000000005EFD1000 Physical table override, new table: 0x000000005DB5B000
    [    0.000000] ACPI: DSDT 0x000000005DB5B000 023EEF (v02 HPQOEM 1909     00000002 INTL 20161117)