Versión: 2.0 Diciembre 2006
Autor: Juan Antonio Martínez < jonsito en teleline punto es >
Este documento indica todos los pasos que he seguido para compilar el kernel-2.4.21-xfs proporcionado por Siemens para el gigaset m740av en un entorno de desarrollo cruzado bajo Linux Fedora Core 5
Se incluye tambien documentacion sobre cómo compilar módulo adicionales, mediante dos ejemplos: fuse y cddafs, así como una versión preliminar de las instrucciones para incluír un nuevo kernel en la imagen de firmware
Este no es un documento sencillo: se requiere experiencia en el entorno de desarrollo Linux, así como conocimientos sobre cómo compilar un núcleo Linux nativo en un PC.
Este documento es copyright 2006 de Juan Antonio Martínez Castaño.
Se autoriza su libre copia y distribución en cualquier formato, incluyendo medios electrónicos siempre y cuando se conserve integra su literalidad, especialmente en esta nota de copyright
Se autoriza su modificación, y la distribución de copias modificadas, siempre que dicha copia incluya una cláusula indicando su calidad de trabajo derivado, haga mención al autor original y proporcione un enlace al documento original
Versión 2.0 15-Dic-2006
root# yum install compat-gcc-32
Antes de empezar, es recomendable leer en su totalidad el documento, y entender perfectamente qué se hace en cada paso. El lector deberá en su caso adaptar los comandos que se indican, ajustando los directorios y variables a su caso concreto
Volver al índiceEn esta primera fase, creamos el espacio de trabajo, descargamos las aplicaciones necesarias, las compilamos e instalamos
Al contrario que en un procedimiento normal para construír una cross-toolchain, para compilar el kernel no es preciso compilar la glibc/uClibc, o compilar el entorno de desarrollo completo C/C++. Recordemos que el kernel está escrito enteramente en C/ensamblador, y no utiliza librerías externas
La pregunta obvia: si ya existe un paquete para desarrollos cruzados para el M740AV, por qué no utilizarlo... Doy fe de que lo he hecho... y no funciona: si bien puedes compilar e instalar tanto el kernel como los diversos módulos, el API binario entre el egcs-1.1.2 y el gcc-3.2 es "ligeramente" distinto, pero lo suficiente como para que no pueda interrelacionar con el kernel que proporciona Siemens.
Es pues preciso utilizar el mismo kernel y el mismo compilador que el que utiliza Siemens, y de ahí el tener que desarrollar una toolchain propia
Veremos un ejemplo de lo anterior a la hora de compilar el módulo fuse (Filesystem in User Space). Esta aplicación tiene dos partes: un módulo del kernel, y una aplicación de usuario, que deben ser compiladas de manera separada y con distintas toolchains
root# yum install compat-gcc-32 root# export BASEDIR=/path/al/directorio/base/donde/voy/a/trabajar root# mkdir -p ${BASEDIR} root# cd ${BASEDIR} root# mkdir -p toolchain sources root# export PREFIX=${BASEDIR}/toolchain root# export TARGET=mips-linux root# cd ${BASEDIR}/sources root# wget http://oasis.dit.upm.es/~jantonio/m740av/egcs-1.1.2.src.tar.bz2 root# wget http://oasis.dit.upm.es/~jantonio/m740av/egcs-1.1.2.diff.gz root# wget http://oasis.dit.upm.es/~jantonio/m740av/binutils-2.16.1.src.tar.bz2 root# wget http://oasis.dit.upm.es/~jantonio/m740av/depmod.pl root# wget http://oasis.dit.upm.es/~jantonio/m740av/gigaset_m740av_gplsw_1495_14711CF.tar.bz2
root# tar jxvf sources/binutils-2.16.1.src.tar.bz2 root# cd binutils-2.16.1 root# CC=gcc32 ./configure --target=$TARGET --prefix=$PREFIX --disable-nls root# CC=gcc32 make all install root# cd ..
root# tar jxvf sources/egcs-1.1.2.src.tar.bz2 root# cd egcs-1.1.2/ root# zcat ../sources/egcs-1.1.2.diff.gz | patch -p1 root# CC=gcc32 ./configure --target=$TARGET --prefix=$PREFIX --disable-nls \ --enable-languages=c --without-headers --with-newlib --with-gnu-as --with-gnu-ld root# PATH=$PATH:$PREFIX/bin make all-gcc LANGUAGES="c" CFLAGS=-DSYS_SIGLIST_DECLARED root# PATH=$PATH:$PREFIX/bin make install-gcc LANGUAGES="c" CFLAGS=-DSYS_SIGLIST_DECLARED root# cd ..
Con esto ya tenemos preparado el cross-toolchain para poder compilar el kernel
Volver al índiceEn esta fase vamos a extraer los fuentes del kernel de Siemens, instalarlos en nuestro directorio de trabajo, y proceder a compilarlo, generando de paso una serie de módulos que no vienen de serie y que nos pueden ser útiles
En su momento lo volveremos a repetir, pero nunca estará de msáas: NUNCA, NUNCA, BAJO NINGUN CONCEPTO debemos cambiar las opciones que vienen de serie en aquellas partes del kernel que no vengan en la configuración por defecto definidas como módulos. Podemos añadir, reconfigurar y quitar módulos, pero nada más
De no hacerlo así, romperíamos las dependencias de símbolos que el kernel precompilado que ofrece Siemens incluye, y no podríamos hacer insmod de nuestros módulos. O mucho peor aún: si cambiáramos el kernel que ofrece Siemens, no funcionarían los módulos propietarios que Siemens ha compilado... con lo que nuestro gigaset se convertiría en una chatarra muy cara....
Por ejemplo: podemos añadir como módulo el soporte para una webcam, pero no podemos INCLUIR dicho soporte en el kernel. Del mismo modo, el soporte SCSI viene incluído en el kernel, por lo que no podemos extraerlo y ponerlo como módulo
Otro detalle adicional: aunque podemos compilar muchos drivers como módulos, no siempre podremos utilizarlos.... pues es necesario que exista una entrada /dev en el root filesystem para acceder a ellos
Por ejemplo: podemos añadir el módulo iso9660 para soporte de sistema de ficheros ISO9660 ( CD-Rom ), con lo que podrémos montar imágenes ISO... en modo loop. Pero si queremos montar un CD-ROM, necesitaremos el módulo cdrom... que necesita a su vez e módulo sr_mod, y que a su vez necesita la entrada /dev/scd0 en el root filesystem
Se sugiere pues, conocimientos sobre generación de nuevos firmwares y cambios del rootfs en el gigaset...
Crear un directorio de trabajo
Descomprimir y extraer los fuentes del kernel
root# mkdir -p toolchain/usr/src root# tar jxvf sources/gigaset_m740av_gplsw_1495_14711CF.tar.bz2 root# ( cd gigaset_m740av_gplsw/linux-2.4-xfs ; tar cfBp - linux ) | ( cd toolchain/usr/src; tar xfBp - )
Nos vamos al directorio de trabajo y ajustamos los nombres con el convenio "estandard"
root# cd ${BASEDIR}/toolchain/usr/src root# mv linux linux-2.4-xfs && ln -s linux-2.4-xfs linux root# cd linux
Hacemos una copia de seguridad de la configuracion original. De esta manera, ante "desastres" siempre podemos dejarlo como estaba...
root# cp .config config.Siemens
Ponemos el directorio drivers/usb correcto. Parece ser que Siemens utiliza una versión propia de los drivers USB. A la hora de realizar el "make modules_install", el Depmod se encuentra con problemas de dependencias, que se soluciona poniendo los nombres de los subdirectorios correctos:
root# mv drivers/usb drivers/usb.back root# mv drivers/usb.2.4.21 drivers/usb
Toqueteamos los Makefiles para arreglar los paths, de manera que apunten a nuestra toolchain. Por si acaso, hacemos copias de seguridad
root# cp Makefile Makefile.orig root# cp arch/mips/Makefile arch/mips/Makefile.orig root# vi Makefile arch/mips/Makefile
Los cambios son muy simples:
Comprobamos que los includes están correctos. Para ello debemos asegurarnos que el fichero include/asm-mips/setup.h exista ( aunque esté vacío ) y que exista el enlace simbólico include/asm apuntando a include/asm-mips
root# [ -f include/asm-mips/setup.h ] || touch include/asm-mips/setup.h root# ln -sfn include/asm-mips include/asm
Editamos configuración del linker para adaptarlo a nuestras binutils
root# vi arch/mips/ld.script.in
Donde pone 'OUTPUT_FORMAT("elf32-bigmips")' ( primera linea )
debe poner 'OUTPUT_FORMAT("elf32-big")'
Con esto ya tenemos preparados los fuentes para empezar a trabajar. En sentido estricto alguno de estos cambios no son necesarios ( en concreto el enlace simbólico asm -> asm-mips ), pero dado que venían en la documentación original, he preferido mantenerlos....
Ahora es cuando de verdad vamos a empezar a trabajar:
Vamos a compilar el kernel, añadiendo varios módulos nuevos:
Volvemos a recordar: NUNCA SE DEBE MODIFICAR LA CONFIGURACION ESTANDARD, sino solamente añadir o borrar módulos
Hacemos limpieza y restauramos la configuración que nos da Siemens:
root# make distclean root# cp config.Siemens .config
Lanzamos "make menuconfig" y ajustamos las nuevas opciones:
root# make menuconfig
Activar "keyboard", "mouse" y "event interface" como módulos
Activación del input layer (/dev/input)
Input core support -> ( activar como módulo ) <M> Input core support <M> Keyboard support <M> Mouse support (720) Horizontal screen resolution (NEW) (576) Vertical screen resolution (NEW) < > Joystick support <M> Event interface support |
Activación de dispositivos HID por USB
Usb support -> ( buscar USB Human Interface Devices ) y habilitar: .... --- USB Human Interface Devices (HID) <M> USB Human Interface Device (full HID) support [*] HID input layer support [*] /dev/hiddev raw HID device support <M> USB HIDBP Keyboard (basic) support <M> USB HIDBP Mouse (basic) support .... |
Por último añadimos el soporte para iso9660 y UDF
--- File systems .... <M> Journalling Flash File System v2 (JFFS2) support (0) JFFS2 debugging verbosity (0 = quiet, 2 = noisy) <*> Compressed ROM file system support [ ] Virtual memory file system support (former shm fs) <M> ISO 9660 CDROM file system support [*] Microsoft Joliet CDROM extensions [ ] Transparent decompression extension < > JFS filesystem support < > Minix fs support .... < > ROM file system support <*> Second extended fs support < > System V/Xenix/V7/Coherent file system support <M> UDF file system support (read only) [ ] UDF write support (DANGEROUS) < > UFS file system support (read only) <M> XFS filesystem support [ ] ACL support .... |
Volvemos a insistir: NUNCA marcar con <*> ( insertar en el kernel ) ninguna opción nueva, ni modificar o eliminar ninguna opción así marcada en la configuración que nos ofrece Siemens. Solo se puede añadir/borrar/editar lo marcado con <M> (módulo)
De lo contrario, todo nuestro trabajo no solo no servirá para nada, sino que nos podemos cargar el gigaset...
Guardamos la configuracion por si acaso en un fichero "config.mine" Salimos guardando nueva configuración
Por fin: vamos allá:
root# make dep; make clean; root# make vmlinux root# make modules root# make modules_install
Tras este proceso se obtiene:
El make modules_install nos pone todo en /lib/modules/linux-2.4-xfs.
No obstante falla al hacer el depmod -a, por lo que habrá que hacerlo
a mano:
root# /tmp/depmod.pl -v -F System.map -k vmlinux -b /lib/modules/2.4.21-xfs
Una vez comprobado que no hay errores, lo guardamos en el fichero modules.dep, añadimos el fichero System.map, y creamos un paquete tar.gz con los modulos, listo para ser transferido al Gigaset m740av
root# /tmp/depmod.pl -F System.map -k vmlinux -b /lib/modules/2.4.21-xfs >/lib/modules/2.4.21-xfs/modules.dep root# cp System.map /lib/modules/2.4.21-xfs/System.map root# tar zcvf modules-2.4.21-xfs.tar.gz -C / lib/modules/2.4.21-xfs
Evidentemente el directorio /lib/modules/2.4.21-xfs, aunque se ha instalado en el lugar estándar para los módulos del kernel, no es utilizable por nuestro sistema nativo :-), por lo que puede ser borrado
Un problema común relacionado con la aparición de mensajes de unresolved symbols está relacionado con la implementación de Siemens del stack USB: si en "make menuconfig" se habilitan los módulos USB serial devices, dichos módulos mostrarán dependencias fallidas. Por ello es preferible no habilitar dicha opción
Esto es todo amigos. Ahora solo queda copiar el /lib/modules/2.4.21-xfs al disco duro del gigaset, y probar con insmod y rmmod que podemos cargar y descargar dichos modulos sin problemas.
Volver al índiceAhora que ya sabemos cómo compilar el kernel, vamos a darle una vuelta de tuerca y aprender a compilar módulos externos. Para ello hemos escogido dos módulos representativos del trabajo y modificaciones que hay que hacer para realizar compilaciones cruzadas
Una observación: para compilar un módulo externo no es estrictamente necesario haber realizado todo el proceso de compilación del kernel: basta con llegar a la ejecución de "make menuconfig", de manera que se hayan creado todos los ficheros de configuración necesarios en el árbol de directorios
Otro detalle: evidentemente, la mayor parte de los módulos externos pueden integrarse sin problemas en el árbol de directorios del fuente del kernel; pero esto violaría nuestra política de "no-intrusión". Por ello en todos los casos vamos a compilarlos de manera separada al kernel
CDDA FS es un módulo que permite montar un CD de manera que cada una de las pistas se ve como un fichero. Es especialmente útil en los discos multisesión, en los que puedes ver cada sesión por separado, o -sobre todo- en los CD's de audio, en los cuales cada canción es vista como un fichero .wav
La página web del proyecto cddafs es http://www.ii.pw.edu.pl/~borkowsm/cdfs.htm
En este ejemplo nos encontramos con un problema típico: las versiones actualizadas sólo funcionan en el kernel 2.6.X, y no existe una versión para el kernel 2.4.21 Esto significa que deberemos modificar el makefile para engancharlo a nuestro kernel, y que se pueda compilar de forma independiente
Descargamos y descomprimimos el código fuente de cddafs
root# cd ${BASEDIR}/sources root# wget ftp://ftp.ii.pw.edu.pl/pub/opensource/cdfs/cddafs035.tgz root# cd ${BASEDIR} root# tar zxvf sources/cddafs035.tgz root# cd cddafs-0.35
Hacemos una copia de seguridad del makefile original y creamos el nuestro
root# cp Makefile Makefile.orig root# cat <<__EOF >Makefile # KERNEL = /media/disk/m740/kernel-toolchains/toolchain/usr/src/linux O_TARGET := cddafs.o obj-y := main.o file.o dir.o obj-m := $(O_TARGET) include $(TOPDIR)/Rules.make clean: rm -f *.o cddafs.o: main.o file.o dir.o main.o: main.c cddafs.h file.o: file.c cddafs.h dir.o: dir.c cddafs.h __EOF root#
La modificación anterior al Makefile, se debe a que estos fuentes están preparados para una versión distinta de kernel, y además presupone que se iba a incluír como parche en los fuentes. Como aplicamos el principio de no intrusión, y vamos a realizar una compilación separada, hay que hacer este cambio, que estandariza el formato del makefile al kernel 2.4.21
Pronunciamos el conjuro mágico, que debería ser el mantra de todo compilador de módulos:
root# make -C ${BASEDIR}/toolchain/usr/src/linux SUBDIRS=$PWD modules
Esto es, le decimos al kernel que compile como módulo... lo que encuentre en nuestro subdirectorio
Tras la compilación, Obtendremos un precioso fichero cddafs.o objeto de nuestros amores :-). Para instalarlo, bien podemos copiarlo directamente al gigaset y hacer un "insmod" a pelo, o mejor, incluirlo en nuestro árbol de módulos que hemos creado bajo /lib/modules/2.4.21-xfs:
root# mkdir -p /lib/modules/2.4.21-xfs/kernel/fs/cddafs root# cp cddafs.o /lib/modules/2.4.21-xfs/kernel/fs/cddafs/cddafs.o
Ejecutando de nuevo depmod.pl actualizamos la lista de dependencias, que aunque en este caso no es estrictamente necesario, pues nunca está de más
En ocasiones el "make" falla con exóticos mensajes de ficheros no encontrados... En un 99% de los casos, se debe a que no hemos llegado a ejecutar el "make menuconfig" en los fuentes del kernel, o bien hemos hecho un "make distclean"
Esto es todo. Dependiendo del módulo, el trabajo será mas o menos sencillo. lo normal es que haya que editar el Makefile, retocar algún path... y pronunciar las palabras mágicas :-)
FUSE ( Filesystem in USEr space ) es un módulo "puente" que permite a aplicaciones que se ejecuten en espacio de usuario "simular" un sistema de ficheros. Aplicación típica es el sistema de ficheros CIFS, una versión mejorada del smbfs ( sistema de ficheros de red que utilizan los entornos windows )
Fuse puede ser obtenido en su página web: http://fuse.sourceforge.net/
Este ejemplo supone un problema añadido:
La solución consiste en realizar la compilación en dos pasos: módulo y aplicaciones
Descargamos y descomprimimos el codigo fuente:
root# cd ${BASEDIR}/source root# wget http://puzzle.dl.sourceforge.net/sourceforge/fuse/fuse-2.5.3.tar.gz root# cd .. root# tar zxvf sources/fuse-2.5.3.tar.gz root# cd sources/kernel
Ejecutamos "configure" indicando dónde residen los fuentes del kernel, y habilitando la compilacion del módulo
./configure --with-kernel=${BASEDIR}/toolchain/usr/src/linux --enable-kernel-module
Editamos el Makefile, adaptándolo a las peculiaridades del código fuente de Siemens. Debe quedar de la siguiente manera:
..... # CC = gcc # LD = ld # CFLAGS = -O2 -Wall -Wstrict-prototypes -fno-strict-aliasing -pipe -msoft-float # CPPFLAGS = -I../../toolchain/usr/src/linux/include -I. -D__KERNEL__ -DMODULE -D_LOOSE_KERNEL_NAMES -DFUSE_VERSION=\"$(VERSION)\" fuse_objs = dev.o dir.o file.o inode.o compat/parser.o SUFFIXES = .c .o .s modules: all-spec all-spec: fuse.o .c.o: $(CC) $(CFLAGS) $(CPPFLAGS) -DFUSE_VERSION=\"$(VERSION)\" -c $< -o $@ .....Los cambios consisten en:
make -C ${BASEDIR}/toolchain/usr/src/linux SUBDIRS=$PWD modules
Presuponemos que el lector es ya un experto en compilación cruzada
de aplicaciones, y que tiene correctamente instalado el paquete de compilación cruzada para el Gigaset M740AV.
En caso negativo, me temo que esta documentación le será poco mas que inútil....
Supongamos pues que el paquete m740av-xgcc-1.8.2.zip ha sido descargado, e instalado correctamente.
Sea /usr/local/mips-linux el directorio base de instalación del entorno de desarrollo cruzado
Creamos el siguiente script:
#!/bin/bash export BASE=/usr/local/mips-linux export PATH=$PATH:${BASE}/bin # export INSTALL_DIR=/where/to/install/package AR=mips-uclibc-ar \ AS=mips-uclibc-as \ CC=mips-uclibc-gcc \ CPP=mips-uclibc-cpp \ CXX=mips-uclibc-g++ \ LD=mips-uclibc-ld \ NM=mips-uclibc-nm \ OBJCOPY=mips-uclibc-objcopy \ OBJDUMP=mips-uclibc-objdump \ RANLIB=mips-uclibc-ranlib \ SIZE=mips-uclibc-size \ STRINGS=mips-uclibc-strings \ STRIP=mips-uclibc-strip \ CPPFLAGS="-I${BASE}/usr/include -I${BASE}/include " \ LDFLAGS="-L${BASE}/usr/lib -L${BASE}/lib " \ ./configure --host=mips-linux --build=i386-linux \ --prefix=$INSTALL_DIR/usr \ --sysconfdir=$INSTALL_DIR/etc \ --localstatedir=$INSTALL_DIR/var \ --infodir=$INSTALL_DIR/usr/share/info \ --mandir=$INSTALL_DIR/usr/share/man \ $*y lo guardamos con el nombre de "configure.sh". Este script lo ejecutaremos en lugar del "configure" que nos aparece en el paquete "fuse". Realmente es un wrapper que invoca a éste último, ajustando variables de entorno y directorios de instalació
Ejecutamos nuestro "configure" añadiendo algunos parámetros extras que necesita fuse:
root# CFLAGS="-D_FILE_OFFSET_BITS=64 -DUSE_UCLIBC" ./configure.sh --disable-kernel-module --enable-lib --enable-util --disable-mtabDonde se le dice que:
Una vez hecho esto, basta con ejecutar "make"
root# PATH=$PATH:/usr/local/mips-linux/bin makeSe debe compilar sin más problemas
Ya casi hemos acabado. Ahora vamos a generar un paquete que incluya todo lo relacionado con la aplicación fuse. Para ello vamos a crear un directorio temporal donde hacer el "make install", y vamos a generar un tar.gz con el contenido de dicho directorio.
Creamos directorio temporal de instalación: y ejecutamos install
root# mkdir /tmp/packages PATH=$PATH:/usr/local/mips-linux/bin make DESTDIR=/tmp/packages install
Copiamos al directorio de instalación el módulo del kernel:
root# mkdir -p /tmp/packages/lib/modules/2.4.21-xfs/kernel/fs/fuse root# cp kernel/fuse.o /tmp/packages/lib/modules/2.4.21-xfs/kernel/fs/fuse/fuse.o
Y !por fin! generamos un tar.gz con el paquete, que podemos descargar e instalar en el gigaset, y borramos directorio temporal:
root# tar cvf fuse-m740av-2.5.3.tar.gz -C /tmp/packages * root# rm -rf /tmp/packagesEl paquete que hemos creado contiene:
El último paso consiste -evidentemente- en transferir este paquete .tar.gz al gigaset, descomprimirlo, y comprobar que "insmod fuse" funciona
Volver al índice