Patching DSDT in recent Linux kernels without recompiling

Up until a year or two ago, the Linux kernel let you replace the ACPI DSDT by adding a customized version to the initrd. However, more recent versions disable that by default. If you’re using Grub2 as your bootloader though, the alternative is simple: just add acpi /boot/dsdt.aml to your Grub config. If you prefer a more elegant solution, just add the attached 01_acpi.txt to /etc/grub.d, renamed it to 01_acpi and chmod +x it; then run update-grub2 to rebuild your Grub config. It originally came from ubuntuforums.org and I removed the -e flag in the acpi line, which caused the new DSDT only to be visible to Grub, but not to the OS.

I believe the acpi command in Grub2 originally came from the Hackintosh community – messing around with DSDTs is a lot more common there because Mac OS X is rather picky.

For those of you who don’t know what I’m talking about: the DSDT describes certain hardware features your PC has, such as buttons, CPU power save modes, and lots of other things. Some mainboards have very poorly done BIOSes that have equally messed up DSDT tables. I won’t go into a lot of detail regarding how to fix those here though (it’s as simple as cat /proc/acpi/dsdt > dsdt.dat; iasl -d dsdt.dat; editing dsdt.dsl to your liking; iasl -tc dsdt.dsl (this last step will probably produce a number of errors that can be solved by googling for the error number and making the appropriate changes in dsdt.dsl)).

Another valuable hint for people messing around with DSDTs: the DSDT is not the only place that can contain this kind of information, the other place would be the SSDT and possibly additional SSDTs. You can find them in /sys/firmware/acpi/tables and decompile them just like the DSDT as described above. Instead of recompiling the SSDT by itself, you could probably also consider merging it into your custom DSDT at the appropriate places.

37 thoughts on “Patching DSDT in recent Linux kernels without recompiling

  1. Adrian

    Glad to find the useful tip. Thanks.

    I have a question about the last one sentence: “you could probably also consider merging it into your custom DSDT at the appropriate places.” Could you kindly provide the steps for merging SSDT into the custom DSDT?

  2. Michael Kuron Post author

    @Adrian: Just copy the contents from SSDT.dsl to DSDT.dsl and place them at a syntactically correct place (iasl will complain if you do it wrong). If identically-named sections exist both in DSDT and SSDT, you can usually replace the one in DSDT with the one from SSDT (though you might want to google to find out what that section name does — some sections appear to be allowed multiple times). If you upload your disassembled DSDT and SSDT to pastebin.com or something, I could take a look at it and give it a try.

  3. rod

    Eric, I’m following your recomendation of using grub instead of recompiling kernel. The custom downloadable kernel does work, but it kills the 3d nvidia acceleration with the propietary drivers. My question is: in Patching DSDT post the man mention a DSDT.aml to add in grub… but the files after extracting, disassemby and reasembli are .dat .hex and .dsl.
    ¿How exactly do you use your custom DSDT in grub? I am missing the step that trasform to .aml
    Thanks

  4. Nicholas Hunsicker

    Just wanted to say that I came over from the tech interplay page about fixing the toshiba battery issue as well, and I have this working now over here. For those that are totally clueless about messing with /etc/grub.d you need to remember to run an update-grub2 afterward otherwise you’re not going to see any change.

  5. ido

    Thanks for the post. Combined with the post in techinterplay.com, now I don’t have to endure “the torturing 2 hours” of recompiling anymore just to have the battery indicator light up in my desktop.

    By the way, I wonder what is the real function of -e in the first line of 01_acpi files ?

  6. Veer

    Hello Michael Kuron ,

    I have added the file 01_acpi.txt in to /etc/grub.d after changing the permission as you mentioned.
    Then I have edited the file DSDT.dsl as per the instruction of techinterplay.com. And recompiled the dsdt.dsl using the command iasl -tc dsdt.dsl. Finally I updated the grub. Unfortunately the battery meter is not showing up on my LinuxMint. Could you please assist me to resolve the issue?

  7. Michael Kuron Post author

    Is that grub2? Did you remove the .txt extension and then chmod +x it? If you did everything correctly, you’ll get a line saying that it found an ACPI table when you run update-grub2 to rebuild the grub config.

  8. Veer

    Hello,

    Thank you very much for your promptly reply. I have removed the extension and changed the permission as you mentioned. However the update grub is not showing found acpi table. Should I try once again?

  9. Veer

    Hello Michael Kuron,

    I apologize for the misinformation. I am using grub 1.99. Is it possible to fix the issue?

  10. Michael Kuron Post author

    I believe 1.99 is already grub2, I’m running 1.98 and that’s definitely grub2. Grub 1 lacks essential features, most notably the acpi command itself, so that wouldn’t work.
    Other than what I wrote previously, there’s nothing I can suggest (it should just work), so you’re on your own there. If you find out what’s causing the issue, please do post it. A good starting point would be to add an echo line to the script and see whether that gets output when running update-grub2. Also, please make sure that your recompiled DSDT is at /boot/dsdt.aml (case-sensitive), as that is where the script looks.

  11. Veer

    Hello Michael Kuron,

    Additional information if it will help the DSDT is located in /sys/firmware/acpi/tables/ instead of cat /proc/acpi.

    Thanks.

  12. AMAR

    Hi,

    I am also getting error “Non-ascii input file – DSDT.dsl” while recompiling the DSDT.dsl.

    thanks.

  13. Michael Kuron Post author

    Did iasl -d dsdt.dat yield the proper text file which you edited and does that error occur when you do iasl -tc dsdt.dsl? Maybe your iasl version has a bug (I used 20100528 from Debian Squeeze which worked fine) or your text editor screws up character encoding — it’s kind of hard to tell without knowing the details.

    Also, there are many places around the internet that explain how to recompile a DSDT and how to use iasl, neither of which my original blog post talked about — so I’d prefer to keep the comments restricted to the actual process of injecting the dsdt.aml.

  14. Jasmine Hassan

    This should be added to Kernel Documentation/acpi/override*.txt

    Danke shen :)

  15. Pingback: HP 8710p and Linux « Egon Rath – Blog

  16. Michael Kuron Post author

    The commands for decompiling and recompiling (iasl -d and iasl -tc) have been mentioned several times here. Any further questions for them will get deleted.
    Any comments asking for help with specific iasl warnings will also get deleted. There are so many resources for DSDT fixing around the internet that can help you — Google is your friend.

  17. Mike

    This fix solves battery monitor update problem on Toshiba Satellite C655 (and probably other Toshiba models) running Ubuntu (Kubuntu) 11.10.

  18. Mike

    Spoke too soon… I knew I should have more fully tested this. :)

    On the Toshiba C655 the battery drain is updated, but the charging is not.

    Helpful if you want to know how much battery you have left when running on the battery, but doesn’t provide you with an update on the charging status. Have to unplug/plug in to get the current charge.

  19. gamma

    Hey, thank you very much. I finally managed to fix my battery problem without compiling the kernel. :-)

  20. arnold

    For it worked when I first followed the Techinterplay section to fix dsdl (http://techinterplay.com/fix-toshiba-battery-issue-linux.html).
    sudo su
    # cat /sys/firmware/acpi/tables/DSDT > DSDT.dat
    # iasl -d DSDT.dat
    # gedit DSDT.dsl

    do not copy/paste when you do the following, or you will get the error “Non-ascii input file – DSDT.dsl” when you try to compile!

    search for line : OperationRegion (EMEM, SystemMemory, 0×FF808001, 0×FF)
    and replace it with : OperationRegion (EMEM, EmbeddedControl, 0×00, 0×FF)
    save the file.

    # iasl -tc DSDT.dsl

    then I had to rename and move the .aml:
    # mv DSDT.aml /boot/dsdt.aml

    Then I followed this blog’s advice:
    …add the attached 01_acpi.txt to /etc/grub.d, renamed it to 01_acpi and chmod +x it; then run update-grub2…

    …happy now:)

  21. Michael

    I’ve tried your /etc/grub.d script and experienced the following problem:

    error: hd0 read error.
    error: hd0 read error.
    error: hd0 read error.
    error: hd0 read error.
    error: hd0 read error.
    error: hd0 read error.
    error: hd0 read error.
    error: hd0 read error.
    error: hd0 read error.
    assert: error stack overflow detected!
    error: hd0 cannot get C/H/S values.
    error: no such device: c42eea91-ed22-4ac5-9ddc-a9070f1080b6
    error: hd0 cannot get C/H/S values.
    error: hd0 cannot get C/H/S values.

    After that, grub gets me back into the menu from where I can select a kernel, which results in a similar error:

    error: hd0 cannot get C/H/S values.
    error: hd0 cannot get C/H/S values.

    This error only disappears when rebooting the system into a live CD, modifying the grub.cfg and removing the grub acpi option. I guess that there may be something wrong with my dsdt.aml, although it does not have any compile errors.

    Therefore, I propose an intermediate solution for easy debugging: /etc/grub.d/21_acpi

    [prefix code from /etc/grub.d/01_acpi here]

    # Load custom ACPI table
    if [ x${GRUB_CUSTOM_ACPI} != x ] && [ -f ${GRUB_CUSTOM_ACPI} ] \
    && is_path_readable_by_grub ${GRUB_CUSTOM_ACPI}; then
    cat <&2
    prepare_grub_to_access_device `${grub_probe} –target=device ${GRUB_CUSTOM_ACPI}` | sed -e “s/^/ /”
    cat << EOF
    acpi (\$root)`make_system_path_relative_to_its_root ${GRUB_CUSTOM_ACPI}`
    }
    EOF
    fi

  22. Michael

    I’ve found out that –no-edba fixes the problem from my last comment. However, I do not know how effective my update then is.

  23. Adam

    I’m new to Ubuntu but am running 12.04 and have the same issue with the battery showing as not present; i’ve followed the instructions from here and Techinterplay but i’m stuck at the part:

    search for line : OperationRegion (EMEM, SystemMemory, 0×FF808001, 0×FF)
    and replace it with : OperationRegion (EMEM, EmbeddedControl, 0×00, 0×FF)
    save the file.

    I cannot find this line in the DSDT.dsl file at all so assume this fix doesn’t apply to 12.04?

  24. David Rodrigues

    Hey Micheal,
    I’m facing the same problem as you are:

    (The grub problem –
    ….
    error: hd0 read error.
    error: hd0 read error.
    assert: error stack overflow detected!
    error: hd0 cannot get C/H/S values.
    etc… etc….)

    I’ve tried using your code for creating 21_acpi but it doesn’t seem to get accepted while generating grub.cfg.

    Could you tell me how you used it or if you have found another solution to your battery problem?

    Thanks

  25. Michael

    Well, I’ve not found any real solution to the problem yet :/ Next I’ll try to compile the DSDT directly into the kernel.

  26. David Rodrigues

    Hey I compiled it using the techinterplay instructions. Although the kernel worked fine, it still didn’t give any battery indicator. If your compiled kernel gets the indicator could you send me a copy at this (davidlandofnod@gmail.com) email address? Thanks in advance.

  27. Andrew

    totally worked! Thanks so much for the cleaner fix for my battery woes!

  28. Ashish Singh

    I did the mentioned step and got my battery meter and status running in Ubuntu 12.04. However, I have dual boot system in my Toshiba Satellite L645 with Windows 7. It seems that modifying the boot loader has caused my Windows to throw error “BIOS error – non compliance ACPI” and does not load. When I removed the files DSDT.dsl and 01_acpi from their respective folders, Windows works but I don’t have battery status in Ubuntu. Any suggestions ?

  29. Michael Kuron Post author

    You most likely screwed up the DSDT while modifying it. Try doing that step by step and see which step breaks it and then google around to see if someone has a fix.
    Alternatively, you could modify /etc/grub.d/10_linux to only run the acpi command when you boot Ubuntu (instead of running it right away when entering Grub).

  30. Ashish Singh

    @Michael Kuron – Thank You for your reply. I did not actually modified the DSDT but downloaded a copy of it. I’m not sure how to do step by step break down of it. Also could you specify what should I edit in /etc/grub.d/10_linux so it doesn’t effect Winodws. Thanks again !!!

  31. Michael Kuron Post author

    If you downloaded a DSDT.aml, it most likely isn’t even compatible with your computer. DSDTs are highly device-specific and even vary between revisions of the same hardware and might be modified during BIOS updates. Therefore: always modify the DSDT yourself.

  32. Ashish Singh

    I tried to edit DSDT myself. First of all, I couldn’t do cat /proc/acpi/dsdt since there are no such file there. So, I did cat /sys/firmware/acpi/tables/DSDT > DSDT.dat .Then I disassembled it using iasl -d DSDT.dat. I noticed that DSDT.dsl already has the line “OperationRegion (EMEM, EmbeddedControl, Zero, 0×FF)” so there is nothing to edit. So I built it again mv dsdt.aml ito /boot/dsdt.aml and did update-grub2. However, I still have the same issue. Also, I notice that in Ubuntu, I don’t have Suspend mode, just Hibernate.

  33. Ashish Singh

    Nevermind, I got it resolved. cat /sys/firmware/acpi/tables/DSDT > DSDT.dat was just outputting the incompatible DSDT.aml file that I had downloaded. Everything seems to be working now. Thanks for bearing with me.

  34. Pingback: Masalah Power Meter Toshiba Satellite L740 di Debian 7 | Abah Sidi

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>