When I installed Debian on my new laptop earlier this year, I was impressed by how easy it was to set everything up. However, I had to cope with a nagging bug: My system couldn’t recognize the battery, so I had no idea how much time I had before running out of power. It turns out that sloppy Windows programmers at Toshiba shipped my Satellite L640 laptop with broken firmware that had to be fixed before the Linux kernel would recognize my battery.
It is necessary to recompile Linux to override the DSDT file. A succession of clumsy mistakes made this a miserably drawn-out process for me, but when it’s done correctly it’s reasonably simple. Following are the steps I took to override the DSDT on my 64-bit system running Debian GNU/Linux 6.0.2 (squeeze).
Step 1: Fix the DSDT File
See this helpful article for more details: http://techinterplay.com/fix-toshiba-battery-issue-linux.html.
Get the original DSDT from the machine:
$ sudo cat /sys/firmware/acpi/tables/DSDT > dsdt.dat
Disassemble it, installing the package iasl if necessary:
$ iasl -d dsdt.dat
Using your favorite editor (mine’s Vim), open up the newly-created dsdt.dsl and replace the line
OperationRegion (EMEM, SystemMemory, 0xFF808001, 0xFF)
with
OperationRegion (EMEM, EmbeddedControl, 0×00, 0xFF)
Save as dsdt-fixed.dsl and exit. Now reassemble:
$ iasl -tc dsdt-fixed.dsl
This creates the file dsdt-fixed.hex which we will compile into the kernel. You can ignore the errors and put the file somewhere in your /home directory for safe keeping (e.g., /home/user/src/dsdt/).
I made the mistake of saving it under /root even though I was running make as me. Wasting hours compiling only to find it didn’t work is no fun, so don’t do that. Don’t put it in the kernel include/ directory either because, on my system anyways, it won’t compile at all.
Step 2: Compile Linux with Custom DSDT
I had never compiled Linux before, so I followed the steps at the Debian wiki: http://wiki.debian.org/OverridingDSDT.
You may need to install build dependencies:
$ sudo aptitude install fakeroot build-essential devscripts $ sudo aptitude build-dep linux-2.6
Find out what kernel you’re running and download its source to a convenient folder (e.g., /home/user/src/):
$ uname -r 2.6.32.5-amd64 $ cd src/ $ apt-get source linux-image-2.6.32-5-amd64 $ cd linux-2.6-2.6.32/
Note: If you have additional repositories such as squeeze-backports, make sure that you’re not downloading a different kernel source by temporarily commenting the relevant deb-src line out of /etc/apt/sources.list and updating apt. The squeeze-backports kernel, 2.6.39, will build, but I had some networking problems with it.
Add a comment to the changelog (e.g., “Custom dsdt”):
$ dch --local +dsdt
Edit debian/config/defines and append an identifier (e.g., “dsdt”) to the value of abi.abiname. This will be added to the name of the new kernel package. Then do this:
$ make -f debian/rules source-all $ fakeroot make -f debian/rules.gen setup_amd64_none_amd64
Edit the file debian/build/build_amd64_none_amd64/.config so that it contains the lines:
CONFIG_STANDALONE=n CONFIG_ACPI_CUSTOM_DSDT=y CONFIG_ACPI_CUSTOM_DSDT_FILE="/home/user/src/dsdt/dsdt-fixed.hex"
Finally, it is time to compile the kernel. Set the “DEBIAN_KERNEL_JOBS” option to the number of CPUs on your machine to help speed things up; it will still take forever, so be patient:
$ time fakeroot make -f debian/rules.gen binary-arch_amd64 binary-indep DEBIAN_KERNEL_JOBS=4
This took almost three hours on my 2.67GHz processor:
real 164m18.577s user 408m31.336s sys 45m18.594s
Note: Running this command directly from the console saves a little time—about 15 minutes on my machine—when compiling. Log out of your desktop, go to tty1 (Ctrl+Alt+F1), log in, and kill your display manager (e.g., $ sudo killall gdm3). After you’ve run the command above in your source directory and generated the kernel image, start X up again (e.g., $ sudo gdm3 start) and log back in.
Note: Actually, it’s probably easier just to run it in a SCREEN session that you can attach or detach from as desired.
If you know what you’re doing (I don’t), you can considerably cut compile time by customizing the kernel yourself and removing extraneous drivers and such.
If all goes well, src/ should be filled with .deb files, including our new kernel image. Install it with dpkg (as root):
$ sudo dpkg -i linux-image-2.6.32-5-dsdt-amd64_2.6.32-35+dsdt1_amd64.deb
Reboot, and Linux will (hopefully) recognize your battery!
$ acpi -V Battery 0: Discharging, 32%, 01:11:16 remaining Battery 0: design capacity 5600 mAh, last full capacity 5188 mAh = 92% Adapter 0: off-line
If you have custom modules, you need to compile them too—so see the wiki on that. Until the Linux developers add a workaround upstream, this process will be necessary whenever you upgrade to a new kernel.
Note: After installing virtualbox I regretted not keeping all of the .deb files I made. In order to compile custom modules (like vboxdrv), you also need to install the linux headers for your new kernel:
$ sudo dpkg -i linux-headers-2.6.32-5-dsdt-amd64_2.6.32-35+dsdt1_amd64.deb \ linux-headers-2.6.32-5-dsdt-common_2.6.32-35+dsdt1_amd64.deb
Keep backups of these files if you think you might need them, otherwise you’ll have to compile again like I did.

