Compilar kernel en Ubuntu con soporte Smart Battery y Software Suspend 2

Actualización I Nuevo método para Smart batteries en Ubuntu más sencillo.

He pasado unas cuantas horas trasteando con el kernel en Ubuntu, queria activar un par de cosas:

  • Soporte para Smart Battery: como ya he comentado en otras ocasiones, el soporte para smart batteries (la que tiene mi portátil) se esta desarrollando en estos momentos pero ya existen parches usables. Me molesta no poder saber el estado de la bateria y queria esta funcionalidad ya.
  • Posibilidad de suspender o hibernar el equipo, es decir, a memoria RAM o a SWAP. La mejor alternativa que he encontrado es Software Suspend 2 que te permite hibernar el equipo (guardando el estado en la SWAP) y recuperarlo tal y como lo dejaste al encenderlo de nuevo.

Lo primero ha sido descargarse las fuentes del kernel, queria utilizar el último disponible y aplicar los parches de Ubuntu para que me funcione lo máximo posible con la distribución (mantener la modularidad y tal para la autodetección de hardware). He añadido al fichero /etc/apt/sources.list:

://archive.ubuntu.com/ubuntu hoary main restricted universe multiverse
deb-src http://archive.ubuntu.com/ubuntu hoary main restricted universe multiverse

He actualizado el listado de aplicaciones y me he descargado el código fuente del último núcleo:

aptitude update
apt-get source linux-image-2.6.10-3-686

Esto me ha creado diversos ficheros:

$ ls
linux-source-2.6.10-2.6.10/
linux-source-2.6.10_2.6.10-10.dsc
linux-source-2.6.10_2.6.10-10.diff.gz
linux-source-2.6.10_2.6.10.orig.tar.gz

* En este punto podemos deshacer ya los cambios del /etc/apt/sources.lists y volver a ejecutar ‘aptitude update’

A continuación he descomprimido el código fuente original del núcleo:

# cd /usr/src
# tar -zxvf /home/user/Downloads/linux-source-2.6.10_2.6.10.orig.tar.gz
# ln -s linux-source-2.6.10-2.6.10 linux

Ahora llega el momento de aplicar los parches necesarios para las smart batteries y el software suspend 2, los descargamos y seguimos las instrucciones.

  1. Descarga del soporte Smart Battery: acpi_sbs-20050120.tar.gz.
  2. Descomprimimos y aplicamos parche:
    # tar -zxvf acpi_sbs-20050120.tar.gz
    # cd /usr/src/linux
    patch -p1 <  /home/user/Downloads/acpi_sbs-20050119/acpi-ec-2.6.10.diff
    
  3. href=”http://developer.berlios.de/project/showfiles.php?group_id=1412″>Software Suspend 2 y del script hibernate:
    # tar -zxvf hibernate-script-1.03.tar.gz
    # cd hibernate-script-1.03/
    # checkinstall ./install.sh
    # cd ..
    # tar -zxvf software-suspend-2.1.5.14-for-2.6.10.tar.bz2
    # cd /usr/src/linux
    /home/user/Downloads/software-suspend-2.1.5.14-for-2.6.10/apply
    

A continuación instalé dpatch para poder aplicar comodamente los parches de Ubuntu:

# aptitude install dpatch
# cd /usr/src/linux
# cp -r /home/user/Downloads/linux-source-2.6.10-2.6.10/debian/ .

Como vamos a aplicar parches sobre un kernel no original, algunos fallaran. Para que no haya problemas de compilación, he aplicado solo aquellos que no fallaban:

dpatch apply stolen-from-head_acpi-20041210
dpatch apply stolen-from-head_fix-cx88-build
dpatch apply stolen-from-head_fix_cap_mod
dpatch apply stolen-from-head_fix-gconfig
dpatch apply stolen-from-head_brk-locked
dpatch apply stolen-from-head_microcode-less-confusing
dpatch apply stolen-from-head_quite-scsi-ioctl
dpatch apply stolen-from-head_early-ali-watchdog-support
dpatch apply stolen-from-head_fix-ibmvscsi-timeout
dpatch apply stolen-from-head_ibm-acpi-exit
dpatch apply stolen-from-head_libata-pio-1
dpatch apply stolen-from-head_libata-pio-2
dpatch apply stolen-from-head_libata-dma-1
dpatch apply stolen-from-head_libata-fixftbs
dpatch apply stolen-from-head_sparc64-stop-referencing-isock
dpatch apply stolen-from-head_prefetching-skb-queue-walk
dpatch apply stolen-from-head_dsmark-ignore-ecn
dpatch apply stolen-from-head_serverworks-CSB6-raid-support
dpatch apply stolen-from-head_zatm-fix
dpatch apply stolen-from-head_mxser-several-fixes
dpatch apply stolen-from-head_cinergy-user-annotation
dpatch apply stolen-from-head_av7110_hw-user-annotation
dpatch apply stolen-from-head_fix-redundant-ide-proc-entry
dpatch apply stolen-from-head_fix-ide-cleanup-module
dpatch apply stolen-from-head_uaccess-annotation
dpatch apply stolen-from-head_intel-ich7-support
dpatch apply stolen-from-head_fix-build-with-no-ipv6
dpatch apply stolen-from-head_fix-fake-anti-optimizer-macro
dpatch apply stolen-from-head_send_sigtrap
dpatch apply stolen-from-head_tf-handling
dpatch apply stolen-from-head_single-step-popf
dpatch apply stolen-from-head_ipt_ECN-corrupt-checksum-fix
dpatch apply stolen-from-head_fix-inet6_sk
dpatch apply stolen-from-head_fix-proc-ip_conntrack_standalone
dpatch apply stolen-from-head_fix-cleanup-path
dpatch apply stolen-from-head_uaccess-annotation-ppc
#dpatch apply stolen-from-head_acpi-video-device-enumeration
dpatch apply stolen-from-head_fix-PT_DTRACE-test
dpatch apply stolen-from-head_fix-single-step-x86
dpatch apply stolen-from-head_more-rockwell-pnp-modems
dpatch apply stolen-from-head_vmscan-total_scanned-fix
dpatch apply stolen-from-head_CS461x-gameport-build-for-real
dpatch apply stolen-from-head_mm-keep-count-of-free-areas
dpatch apply stolen-from-head_simplified-readahead
dpatch apply stolen-from-head_simplified-readahead-congestion-control
dpatch apply stolen-from-head_mempolicy-optimisation
dpatch apply stolen-from-head_mm-overcommit-updates
dpatch apply stolen-from-head_mark_page_accessed
dpatch apply stolen-from-head_do_anonymous_page
dpatch apply stolen-from-head_do-not-collect-page_states
dpatch apply stolen-from-head_fix-ipt_recent-checkentry
dpatch apply stolen-from-head_fix-ip_conntrack_proto_sctp-exit
dpatch apply stolen-from-head_fix-ip_ct_selective_cleanup
dpatch apply stolen-from-head_ipchains_and_ipfwadm_must_die
dpatch apply stolen-from-head_remove-copy-to-user-warnings
dpatch apply stolen-from-head_ipt_recent-should-ipt_registrater_match
dpatch apply stolen-from-head_fix-broken-rst-handling-in-ip_conntrack
dpatch apply stolen-from-head_fix-ide-arch-obsolete-init
dpatch apply stolen-from-head_assign-pkmap-base-dinamically
dpatch apply stolen-from-head_fix-data-code-overlap
dpatch apply stolen-from-head_cyrix-mii-cpuid
dpatch apply stolen-from-head_triple-fault-with-4k-mapping-and-pae
#dpatch apply stolen-from-head_bootloader-type
dpatch apply stolen-from-head_amd64-thermal-monitor
dpatch apply stolen-from-head_amd64-k8-cmp-fix
dpatch apply stolen-from-head_amd64-numa-add-cpu-fix
dpatch apply stolen-from-head_amd64-remove-duplicate-macro
dpatch apply stolen-from-head_amd64-no-vsyscalls-debug
dpatch apply stolen-from-head_amd64-rename-HTVALID2CMP_LEGACY
dpatch apply stolen-from-head_amd64-cmp-add-scheduler-support
dpatch apply stolen-from-head_amd64-add-missing-iomem
dpatch apply stolen-from-head_amd64-missing-newline
dpatch apply stolen-from-head_amd64-print-segfaults
dpatch apply stolen-from-head_amd64-export-phys-proc-id
dpatch apply stolen-from-head_swsusp-handle-errors
#dpatch apply stolen-from-head_kill-On2-in-swsusp
dpatch apply stolen-from-head_fix-noexec-param
dpatch apply stolen-from-head_ipt_REJECT
dpatch apply stolen-from-head_ipt_ECN-needs-tcp
dpatch apply stolen-from-head_fix-capset-wrong-returns
#dpatch apply stolen-from-head_s3-time-too-fast
dpatch apply stolen-from-head_ptracer-death-race
dpatch apply stolen-from-head_modular-megaraid
dpatch apply stolen-from-head_parport_pc_module_parm_mixing
dpatch apply stolen-from-head_alsa-emu10k1-ioctl-fix
dpatch apply stolen-from-head_nfs-client-odirect
dpatch apply stolen-from-head_8390-skb_padto
dpatch apply stolen-from-head_nfs-df-result
dpatch apply stolen-from-head_fix-udf-race
dpatch apply stolen-from-head_turn-on-CRD-8480C-dma
dpatch apply stolen-from-head_ide-wrong-buffer
dpatch apply stolen-from-head_intel-ich7-sata
dpatch apply stolen-from-head_ich3m-quirks
dpatch apply stolen-from-head_fix-cdrom-autoclose
dpatch apply stolen-from-head_overflow-in-nls
dpatch apply stolen-from-head_fix-rlimit-memlock-dos
dpatch apply stolen-from-head_fix-smp-race-condition
dpatch apply stolen-from-head_verify_mm_writelocked
dpatch apply stolen-from-head_acct_stack_growth_nitpicks
dpatch apply stolen-from-head_ehci-dies-on-startup
dpatch apply stolen-from-head_vesafb_failure_probing
dpatch apply 029-random_poolsize_overflow
dpatch apply 030-moxa_user_copy_checking
dpatch apply 031-sg_scsi_ioctl_int_overflows
dpatch apply untrusted-user-data
dpatch apply amd64-memset
dpatch apply ia64-fix-ftbfs
dpatch apply powerpc-fix-ftbfs
dpatch apply doc-post_halloween
dpatch apply drivers-ide-dma-blacklist-toshiba
dpatch apply drivers-input-psaux-hacks
dpatch apply drivers-net-8139too-locking
dpatch apply drivers-scsi_changer
dpatch apply drivers-scsi-generic_proc_info
dpatch apply fs-asfs
dpatch apply ipsec-missing_wakeup
dpatch apply modular-ide
dpatch apply modular-ide-pnp
dpatch apply modular-vesafb
dpatch apply remove-references-to-removed-drivers
dpatch apply powerpc-pegasos
dpatch apply powerpc-g4-l2-flush-errata
dpatch apply ia64-generic-no-smp
dpatch apply ia64-generic-no-smp-1-to-2
dpatch apply evms-bd-claim
dpatch apply mppe
#dpatch apply ieee80211
#dpatch apply ipw2100
#dpatch apply ipw2200
#dpatch apply ipw2100-fsam7400
#dpatch apply ipw2100-fix-suspend-resume
#dpatch apply ipw2200-fix-suspend-resume
#dpatch apply wlan-ng-prism2-usb
dpatch apply powerpc-serial
dpatch apply powerpc-via82cxxx
#dpatch apply acx100-2
#dpatch apply acx100-kill-float-2
#dpatch apply adm8211
dpatch apply ndiswrapper1.0
dpatch apply eagle-usb
#dpatch apply acx100-fw-3
dpatch apply powermac73
dpatch apply acpi-psparse-aml-crash
dpatch apply sparc-sunzilog-timeout
dpatch apply sparc32-initrd-memcpy
dpatch apply sparc64-hme-lockup
dpatch apply tty-locking-fixes9
dpatch apply smbfs-overflow-fixes-2
dpatch apply inotify-0.17-rml-2.6.10-2
dpatch apply sparc64-inotify-0.17-rml-2.6.10-2
dpatch apply drm-fixes
dpatch apply sk98lin-update-2
dpatch apply synaptics-cpad-support
#dpatch apply acx100-ia64
#dpatch apply ia64-prism2
dpatch apply dsdt-initrd
dpatch apply swsusp-userspace
dpatch apply wakeup_gdt

dpatch apply drivers-usb-pwc
dpatch apply marvell-pegasos-2
dpatch apply cloop
dpatch apply resume-finish-split
dpatch apply panasonic_acpi
dpatch apply sony_acpi
dpatch apply tosh_acpi
dpatch apply fix-ax25
dpatch apply misrouted-irq
dpatch apply b44
dpatch apply ibm_acpi
dpatch apply route-irq-again
dpatch apply alsa-order-cards
dpatch apply thaw_processes

A continuación hay que configurar el kernel, como configuración base podemos coger la del kernel de Warty (/boot/config-2.6.8.1-4-386) o la de Hoary (/home/user/Downloads/linux-source-2.6.10-2.6.10/debian/config/i386/686) y siempre viene bien darse un paseo por el menu de configuración del núcleo por si queremos activar algo más (en mi caso active el soporte PCMCIA, concretamente Yenta Socket… no se pq motivo estaba desactivado).

# cp /boot/config-2.6.8.1-4-386 /usr/src/linux/.config
# cd /usr/src/linux
# make menuconfig

La configuración necesaria para que funcione Smart Battery y Swsusp2 es la siguiente:

# vi /usr/src/linux/.config
...
CONFIG_ACPI=y
CONFIG_ACPI_BOOT=y
CONFIG_ACPI_INTERPRETER=y
CONFIG_ACPI_SLEEP=y
CONFIG_ACPI_SLEEP_PROC_FS=y
# CONFIG_ACPI_AC is not set
# CONFIG_ACPI_BATTERY is not set
CONFIG_ACPI_BUTTON=m
...
#
# Software Suspend 2
#
CONFIG_SOFTWARE_SUSPEND2=m
CONFIG_SOFTWARE_SUSPEND2_BUILTIN=y
CONFIG_SOFTWARE_SUSPEND_SWAPWRITER=m

#
# Page Transformers
#
CONFIG_SOFTWARE_SUSPEND_LZF_COMPRESSION=m

#
# User Interface Options
#
CONFIG_SOFTWARE_SUSPEND_TEXT_MODE=m
...

Ahora ha llegado el momento de compilar el núcleo:

# cd /usr/src/linux/
# make bzImage modules modules_install
# cp arch/i386/boot/bzImage /boot/vmlinuz-2.6.10-686

A continuación tenemos que crear el initrd, como vamos a utilizar swsusp2 tenemos que crear un nuevo fichero /etc/mkinitrd/scripts/swsusp2:

#!/bin/sh

# Put this script in /etc/mkinitrd/scripts/ and regenerate your initrd (by
# "mkinitrd -o /boot/initrd.img-`uname -r`" or reinstall your kernel package.

# Copy in modules
# Note: if you want to add gzip to the list, you'll need zlib_deflate too.

MODULES="suspend_core suspend_block_io suspend_text suspend_swap lzf suspend_lzf"

pushd $MODULEDIR > /dev/null 2>&1
for i in $MODULES ; do
    find -name "$i.ko"
done | cpio -p --make-directories --quiet $INITRDDIR/lib/modules/$VERSION/
popd > /dev/null 2>&1

# Figure out swap device from the first device listed in /proc/swaps
swap_device=`awk 'BEGIN{getline;getline;print$1}' < /proc/swaps`
swap_type=`awk 'BEGIN{getline;getline;print$2}' < /proc/swaps`

if [ "x$swap_type" = "xpartition" ] ; then
    resume2=`perl -e "@a=stat '$swap_device';printf 'swap:%04x', $a[6]"`
else
    echo "Unable to determine swap device! You will need to set resume2= on your"
    echo "kernel command-line manually."
fi

[ -n "$resume2" ] && resume2="echo $resume2 > /proc/software_suspend/resume2"

# Modify linuxrc script

mv $INITRDDIR/linuxrc $INITRDDIR/linuxrc.real
cat <<EOT > $INITRDDIR/linuxrc
#!/bin/sh

export PATH=/sbin:/bin

mount -t proc proc /proc
. /loadmodules
modprobe suspend_core
modprobe suspend_block_io
modprobe suspend_text
modprobe lzf
modprobe suspend_lzf
modprobe suspend_swap
$resume2
echo > /proc/software_suspend/do_resume

rmmod suspend_swap suspend_lzf lzf suspend_text suspend_block_io suspend_core
umount /proc
. ./linuxrc.real
EOT

chmod 777 $INITRDDIR/linuxrc

Y ahora generamos el initrd:

mkinitrd -o /boot/initrd.img-2.6.10-686 2.6.10

En el fichero de configuración del grub (/boot/grub/menu.lst) tendremos que indicar donde se encuentra nuestra partición swap, la cual usará swsusp2 para guardar la información cuando hibernemos:

...
## ## Start Default Options ##
## default kernel options
## default kernel options for automagic boot options
## If you want special options for specifiv kernels use kopt_x_y_z
## where x.y.z is kernel version. Minor versions can be omitted.
## e.g. kopt=root=/dev/hda1 ro
# kopt=root=/dev/hda6 ro resume2=swap:/dev/hda5
...

Y a continuación actualizamos las entradas del grub:

# update-grub

Si todo ha ido bien, ya tenemos el kernel compilado y listo para reiniciar nuestro PC.

En el primer inicio con el nuevo kernel tendremos que compilar los módulos de los drivers de Smart Battery:

# cd /home/user/Downloads/acpi_sbs-20050119
# make
# make install

Si tenemos un Pentium Centrino, es posible que nos interese instalar también el driver para la tarjeta wireless. Se descarga el codigo fuente:

# tar -zxvf ipw2200-0.21.tgz
# cd ipw2200-0.21/
# vi ipw2200.c
* Cambiamos la linea 6607  por "priv->workqueue = create_workqueue(DRV_NAME, 0);"
# make
# make install

También será necesario descargar el firmware y descomprimirlo en /usr/lib/hotplug/firmware/.

Ya solo faltan los últimos retoques al sistema para que todo funcione correctamente, primero añadiremos los modulos de smart battery para que se carguen automaticamente en /etc/modules:

i2c-acpi-ec
acpi-sbs
capability

* El capability se ha de poner tanto si se va a usar Smart Battery como si no.

Mi tarjeta de sonido no funciona correctamente con este kernel y curiosamente para que funcione solo tengo que ejecutar:

alsactl power 0 D3
alsactl power 0 D0

Podemos poner esos comandos en un script de inicio, por ejemplo creamos /etc/init.d/local:

#!/bin/sh
# Init script


. /lib/lsb/init-functions

case "$1" in
start)  log_begin_msg "Starting local init script..."
        #start-stop-daemon --start --quiet --exec
        cp -f /etc/hosts.lan /etc/hosts
        /usr/local/sbin/firewall
        # Necesario para que funcione el sonido
        # (Parece BUG al tener el kernel compilado con swsusp2)
        alsactl power 0 D3
        alsactl power 0 D0
        #log_end_msg $?
    ;;
*)  log_success_msg "Usage: /etc/init.d/local start"
        exit 1
        ;;
esac
exit 0

Ahora ya podemos volver a reiniciar y comprobar que todo funcione correctamente. Podemos ver el estado de la batería con el comando “acpi” o con el applet de gnome correspondiente a la batería.

Para hibernar el equipo tendremos que configurar /etc/hibernate/hibernate.conf, a continuación listo las opciones principales:

### swsusp2_15 (for Software Suspend 2)
UseSwsusp2 yes
Reboot no
EnableEscape yes
DefaultConsoleLevel 1
# ImageSizeLimit 200
## useful for initrd usage:
SuspendDevice swap:/dev/hda5
LoadSuspendModules suspend_swap suspend_lzf suspend_text
UnloadSuspendModulesAfterResume yes

##############################################################################
### Some global settings
##############################################################################

Verbosity 0
LogFile /var/log/hibernate.log
LogVerbosity 1


### clock
SaveClock yes

### filesystems
# Unmount /nfsshare /windows /mnt/sambaserver
UnmountFSTypes smbfs nfs
# UnmountGraceTime 1
# Mount /windows

### lock (generally you only want one of the following options)
# LockConsoleAs root
LockXScreenSaver yes
# LockKDE yes

### modules
# UnloadModules snd_via82cxxx usb-ohci
# UnloadAllModules yes
UnloadBlacklistedModules yes
LoadModules auto
# LoadModulesFromFile /etc/modules

### network
# DownInterfaces eth0
DownInterfaces eth0
DownInterfaces eth1
# UpInterfaces auto

### programs
# IncompatiblePrograms xmms
IncompatiblePrograms gqmpeg mplayer totem xine xmms rhythmbox

Para hibernar simplemente ejecutaremos como root “hibernate”, por ejemplo desde una terminal X. El PC se apagará y en el proximo reinicio se recuperará su estado tal y como se quedó (e.g. con el firefox abierto, el OpenOffice con un documento…).

* Web con información extra sobre Acer Travelmate 4001 WLMI
Autor: marble

This entry was posted in Ubuntu. Bookmark the permalink.

One Response to Compilar kernel en Ubuntu con soporte Smart Battery y Software Suspend 2

  1. Anonymous says:

    Estaba pensando, ¿por qué no mantenemos un repositorio con este kernel así parcheado?. Así no tenemos que repetir todos el mismo trabajo cada vez que sale una versión nueva del kernel de ubuntu.

    Por cierto, muy buen artículo.

Leave a Reply