Overriding your DSDT

Some computers come with a broken DSDT. You can read more about this here. This document describes the Debian specific methods needed to override your DSDT on Debian.

WARNING: It is usually not recommended that you override your own DSDT. Overriding your DSDT with garbage can do physical harm to your computer. You have been warned!

Earlier versions of the kernel on Debian made it easy for you to override your DSDT, using the initrd patch. This meant you could just put your new DSDT in /etc/initramfs-tools/DSDT.aml, and regenerate your initrd by update-initramfs -u -k all, and the new DSDT would be used. However, I think the Debian devs thought this was a security risk, and have since dropped the initrd patch. This means, to override your DSDT, you have to really want it! You have to recompile the kernel.

Fortunately all you have to do is rebuild an official kernel, which is a lot easier than building from scratch.

Fixing your DSDT

Before you go about recompiling your kernel, you need to first fix your DSDT. This is documented here, so I only list the commands with brief explanations.

aptitude install iasl/unstable
cat /sys/firmware/acpi/tables/DSDT > dsdt.dat   # Get the systems DSDT
iasl -d dsdt.dat                                # Disassemble it
iasl -tc dsdt.dsl                               # Reassemble it

Now if the last command above gives you compilation errors or warnings, then you might need to override your DSDT. I'd suggest typing your error message, or parts of your error message into Google, and seeing if someone posted a fix on the forums. Here's the errors I had on my HP 2710p:

bash$ iasl -tc dsdt.dsl
Intel ACPI Component Architecture
ASL Optimizing Compiler version 20090521 [Jun 14 2009]
Copyright (C) 2000 - 2009 Intel Corporation
Supports ACPI Specification Revision 3.0a

dsdt.dsl  8473:                 Return (Package (0x02)
Warning  1099 -      Statement is unreachable ^

dsdt.dsl  8590:                         Wait (\_SB.C1AD, 0x10)
Warning  1104 -        Possible operator timeout is ignored ^

ASL Input:  dsdt.dsl - 16075 lines, 576782 bytes, 7697 keywords
AML Output: dsdt.aml - 71673 bytes, 1198 named objects, 6499 executable opcodes

Compilation complete. 0 Errors, 2 Warnings, 0 Remarks, 2528 Optimizations

I got lucky. There were only two warnings, and no errors. So I probably didn't have to fix the DSDT in the first place. But I decided to fix it anyway: The first warning was obvious to fix -- comment out the unreachable code. Typing the second error message into Google showed someone on the Ubuntu forums with a similar error, and a fix that worked for me: I just had to change the 0x10 to 0xffff to make the second warning go away.

Here's a diff -u showing the fixes:

--- dsdt.dsl    2009-12-28 23:12:50.000000000 -0600
+++ dsdt-fixed.dsl      2009-12-28 23:14:03.000000000 -0600
@@ -8470,11 +8470,11 @@
                 Return (Local0)
-                Return (Package (0x02)
-                {
-                    0x04, 
-                    0x00
-                })
+                // Return (Package (0x02) // Unreachable code
+                // {
+                //     0x04, 
+                //     0x00
+                // })
             Method (C2D3, 1, NotSerialized)
@@ -8587,7 +8587,7 @@
                     Store (0x01, Index (DerefOf (Index (Local0, 0x02)), 0x01))
                     If (And (C05C, 0x40))
-                        Wait (\_SB.C1AD, 0x10)
+                        Wait (\_SB.C1AD, 0xffff) // Changed 0x10 to 0xffff to remove error message. See http://ubuntuforums.org/showthread.php?t=659027&page=2
                     Store (\_SB.C073, Index (DerefOf (Index (Local0, 0x02)), 0x02))

Now once you figured out how to fix the compilation errors, save your new DSDT into the file dsdt-fixed.dsl. Recompile this:

iasl -tc dsdt-fixed.dsl

and it will generate a file called dsdt-fixed.hex. Save this somewhere (say /root/dsdt/dsdt-fixed.hex), as we will use this in the next step.

Recompiling a kernel with your fixed DSDT

Now we get your newly fixed DSDT installed. This involves recompiling a kernel. I'm going to describe how to recompile an official kernel with the necessary modifications. A great guide to recompiling an official kernel can be found here. I'm going to follow most of the steps there (with minimal explanation) and show only what's necessary to override the DSDT.

Install the build dependencies:

apt-get install fakeroot build-essential devscripts
apt-get build-dep linux-2.6

Get the kernel source (replace 2.6.31-2 below with your desired kernel version).

apt-get source linux-2.6=2.6.31-2
cd linux-2.6-2.6.31/
dch --local +dsdt

Now edit debian/config/defines and add dsdt to the value of abi.abiname. Both the machine I'm compiling the kernel on, and the target machine (the one with the broken DSDT) have architecture amd64. If your architecture is different, change appropriately (see debian/rules.gen for possible targets).

make -f debian/rules source-all
fakeroot make -f debian/rules.gen setup_amd64_none_amd64
cd debian/build/build_amd64_none_amd64

Now your task is to edit the .config file in this directory and tell it about your new DSDT. This involves adding the lines


in the appropriate place. To do this, you have a couple of options: You can directly edit this in your favourite text editor (vim). Search for a similar commented out option, and replace it with the appropriate line above.

If you're worried you might mess something up, then you can instead

aptitude install ncurses-dev
make menuconfig

and set the ACPI DSDT file using the menu options. Now once this is done, you need to compile your kernel. This is time consuming:

cd ../../..
fakeroot make -f debian/rules.gen binary-arch_amd64 binary-indep DEBIAN_KERNEL_JOBS=2
cd ..

The DEBIAN_KERNEL_JOBS should be the number of CPU's you have available when compiling your kernel. (Gentoo folks usually advise setting it to one more than the number of CPU's.) Whichever setting you use, you'll still be waiting for a while ;)

If you think you might mess up, it might be a good idea to enable ccache to the above step. aptitude install ccache, and append DEBIAN_KERNEL_USE_CCACHE=true to the last line above. This way, if you need to recompile it will be a lot lot faster.

If this successfully completes, you should have all the .deb packages in the current directory. If you don't have any custom modules (e.g. openafs, broadcom-sta, ndiswrapper), then just do

dpkg -i linux-image-2.6.31-dsdt1-amd64_2.6.31-2+dsdt1_amd64.deb

as root, and reboot your system.

If you have custom modules, then you also need the Linux headers for this. If you install the headers first, then dkms will automatically compile some modules for you (e.g. openafs). As root do

dpkg -i linux-headers-2.6.31-dsdt1-common_2.6.31-2+dsdt1_amd64.deb
dpkg -i linux-headers-2.6.31-dsdt1-amd64_2.6.31-2+dsdt1_amd64.deb
dpkg -i linux-image-2.6.31-dsdt1-amd64_2.6.31-2+dsdt1_amd64.deb

and look in your system log to make sure there was no error produced by dkms. Finally install any modules you might have installed through module-assistant. You have to pass -l 2.6.31-dsdt1-amd64 to tell it to generate these modules for your newly compiled kernel.

m-a -l 2.6.31-dsdt1-amd64 a-i <your favourite module>

Now reboot into your new kernel. You can tell that your new DSDT is in use if you see something like

ACPI: Override [DSDT-  nc65xx], this is unsafe: tainting kernel
ACPI: DSDT @ 0x000000003f7c84c0 Table override, replaced with:

in the output of dmesg. The first thing you should do is to make sure your CPU temperatures and fan voltages are correctly reported.