Archivo de la categoría: Cacharreo

Transmission

Un nuevo avance en mi disco duro multimedia: he conseguido compilar el cliente de bittorrent Transmission. Las ventajas de éste sobre el viejo cTorrent son muchas, en concreto:

  • Código más reciente y mantenido: la última versión de cTorrent es del 14 de junio de 2008, lo que parece indicar que el autor lo ha dejado de lado, mientras que Transmission (versión 1.76) es del 24 de octubre de 2009, además de que ya están preparando la próxima versión (1.80).
  • Soporta cifrado: sólo por esto ya merece una atención especial, porque puede duplicar (o más) el número de sitios de los que descargar ficheros, además de que muchos Torrents que no funcionaban en cTorrent sí lo harán en éste.
  • Soporta uPNP: para los que no lo conozcan, es un estándar que, entre otras cosas, permite que un dispositivo situado detrás de un router con NAT pueda pedirle de manera automática la redirección de los puertos externos que necesite. Esto elimina por completo la necesidad de abrir a mano puertos específicos en el router; simplemente funcionará.

AVISO: a partir de aquí empiezo a tocar en el sistema operativo del disco duro multimedia, lo que significa que estas acciones sólo las deben realizar aquellos que sepan muy bien lo que hacen. Si alguien se carga su disco, será el único responsable.

Avisados estáis.

Aquí podeis descargar el código completamente compilado, junto con los scripts para lanzar todo el sistema (1,2 MBytes), ajustados para el MemUp LX. Como en el caso anterior, hay que editar el fichero btpd para activar o desactivar los servicios que se deseen. He conservado cTorrent por si alguien prefiere utilizarlo de manera puntual (o incluso tener ambos a la vez en marcha, que a saber…), aunque lo normal será tener sólo Transmission y bFTPd. Al igual que en el paquete anterior, hay un fichero con instrucciones más detalladas.

Respecto a como lo compilé, pocas novedades, salvo el hecho de que, por mucho que especifiqué que quería un ejecutable estático, se empeñó en hacerlo dinámico. Encima, al utilizar autoconf y automake, no muestra la línea de comandos que está ejecutando en cada momento, con lo que ni siquiera podía hacer el enlazado «a mano». La solución, afortunadamente, fue tan sencilla como lanzar make V=1, para hacer la salida más verbosa y que lo mostrase. Así pude copiar y pegar la línea y añadir el -static.

Por desgracia, ni siquiera esto fue suficiente porque se empeñaba en enlazar con un fichero .la (libevent.la, para ser exactos), los cuales son para ejecutables dinámicos. La solución consistió en reemplazar ese fichero por un simple *.o, de manera que pudiese coger lo que más le interesase. Finalmente, un strip dejó el ejecutable limpio como una patena. El resultado es que las descargas ahora son más rápidas al contar con más peers, y encima la interfaz ha ganado aún más.

Obviamente, al ser ejecutables estáticos funcionarán en cualquier equipo con un procesador MIPSel y suficiente memoria, lo que permite reutilizarlos para otros discos multimedia. Lo mismo ocurre con los otros ejecutables (bFTPd, cTorrent y Yodctcs).

Aproveché además para hacer un cambio en la organización de directorios. Hasta la revisión anterior, en DOWNLOADS se almacenaban los ficheros temporales de cTorrent, y en BT los ficheros bajados. Para no ensuciar tanto el raíz del disco, he optado por crear dentro de BT una carpeta, ctorrent_tmp, para albergar esos ficheros, y otra, transmission_tmp, para que transmission haga lo propio. Estas carpetas se crean automáticamente si no existen. Si estabais bajando algo con cTorrent y quereis pasarlo a Transmission, basta con abrir el torrent (que estará, bien en ctorrent_tmp, bien en DOWNLOADS)  y, como el directorio de descargas es el mismo para ambos y no ha cambiado, Transmission comprobará la integridad de los datos que hay ahí y seguirá descargando justo desde donde se quedó el otro. Por tanto, una vez pasados los ficheros, es seguro borrar la carpeta DOWNLOADS.

Por último, actualicé el fichero de instrucciones.

Los que quieran acceder al nuevo bittorrent Transmission, sólo deben abrir la IP del disco en su navegador, contra el puerto 9090 (ej: http://192.168.1.101:9090).

Para finalizar, una captura de pantalla del nuevo cliente:

A disfrutar.

Compilacion en masa

En la entrada Emergiendo expliqué como generar un entorno de compilación cruzada basado en Gentoo para poder compilar cosas para nuestro disco duro, pero luego, en FTP-ando, eché todo por tierra al no poner binarios creados por mí. Ahora ya he sido capaz de compilar, así que, para los impacientes, aquí está el paquete con las últimas versiones de CTorrent (3.2.2), BFTP (2.6) y YAOD (0.7.2). Las instrucciones de instalación son las mismas que en el artículo anterior (FTP-ando). Como gran ventaja, algunos fallos de BFTP han desaparecido, y encima la tasa de transferencia ha subido a 3MBytes/seg.

AVISO: a partir de aquí empiezo a tocar en el sistema operativo del disco duro multimedia, lo que significa que estas acciones sólo las deben realizar aquellos que sepan muy bien lo que hacen. Si alguien se carga su disco, será el único responsable.

Pasando ya a la chicha, la razón de que haya tardado tanto es que la cosa no es tan sencilla, por varias razones:

  • Para empezar, el disco duro tiene su propia versión de la uClibc, por lo que la única manera de garantizar que un programa funcione correctamente es compilarlo contra esa misma versión.
  • Por otro lado, en algunas versiones del compilador GCC cambia el fomato binario de las bibliotecas en C++, por lo que también es conveniente utilizar la misma versión de compilador GCC: para garantizar que la interfaz binaria entre la aplicación y las bibliotecas es la misma.
  • Por último, muchos paquetes no se pueden instalar en un sistema mediante compilación cruzada porque su configure hace cosas raras, como comprobar si GCC compila correctamente un programa de prueba… programa que estará en arquitectura MIPS y, por tanto, no correrá en un Intel, abortando el proceso de compilación.

Y si ya la cosa se veía complicada, encima nos encontramos con que Gentoo no tiene la versión de GCC utilizada en nuestro disco duro (la 3.4.4), y que algunas versiones de uClibc (entre ellas la 0.9.28.3, la de nuestro disco duro) no compilan con según qué compiladores o versiones de binutils. El resultado era desalentador.

La primera idea que consideré para resolver el problema fue meter un sistema Gentoo completo en el disco y ejecutar en él las aplicaciones usando chroot. Por desgracia esta solución es muy ineficiente porque necesita mucho espacio en disco y porque las aplicaciones sólo tendrían acceso a los directorios contenidos dentro del chroot, pero nunca a los de fuera.

La segunda idea consistía en intentar generar un conjunto nativo de compilador GCC, binutils y biblioteca uClibc con las versiones correctas a partir de fuentes oficiales. Por desgracia, el proceso es demasiado complejo y tampoco funciona con todas las versiones de GCC, binutils y uClibc que interesaba.

La tercera idea era usar BuildRoot, el entorno de generación de compiladores cruzados de BusyBox. Por desgracia, una vez más, no sólo no tenía las versiones necesarias, sino que tampoco compilaba cualquier combinación.

Por último, la cuarta, que ha sido la que decidí emplear, consiste en compilar estáticamente los programas deseados utilizando un compilador nativo en el propio disco duro multimedia. De esta manera, al no depender de ninguna biblioteca de enlazado dinámico, el programa funcionará en cualquier sistema, ahorrándonos el problema de la incompatibilidad de versiones. Además, al no importar la versión de binutils, GCC ni uClibc, podemos utilizar versiones más modernas, que siempre tendrán mayor seguridad y fiabilidad. Por último, al compilarse en el sistema de manera nativa, no habrá problemas con ficheros configure que hagan cosas «raras». Como inconveniente, necesita más memoria que un programa compilado dinámicamente.

Sin embargo, seguía con el problema de conseguir un toolchain para MIPS que funcionase correctamente, cosa compleja porque en Gentoo hay nueve versiones de GCC, cuatro de binutils y tres de uClibc (sin contar revisiones), y no todas las combinaciones compilan. Además, no bastaba con el toolchain, sino que también necesitaba instalar en nativo Bash, GCC, binutils, uClibc, make y el entorno básico con BusyBox. ¿Por donde empezar? Por desgracia la versión más reciente no compilaba, y no podía probar las 108 combinaciones posibles… O al menos, no a mano, así que hice un pequeño script en python que probase a compilar todas las posibles combinaciones. Lo dejé una noche, y el resultado fue que sólo compilaba con el GCC 3.4.6-R2 y GCC 4.1.2, las Binutils 2.18-R4, 2.19.1-R1 o 2.20, y sólo con uClibc 0.9.30.1-R1. En el resto de casos, o fallaba la generación del toolchain para compilación cruzada, o fallaba la compilación de las utilidades nativas.

Una vez descubiertas las versiones, sólo fue necesario generar un toolchain adecuado para compilación cruzada:

crossdev --target mipsel-unknown-linux-uclibc --without-headers --gcc 4.1.2 --binutils 2.20 --libc 0.9.30.1-r1
emerge-wrapper --init

Luego, compilar e instalar las aplicaciones básicas necesarias para poder compilar (lo he cortado por razones de espacio, pero es una única línea):

emerge-mipsel-unknown-linux-uclibc  =binutils-2.20 =gcc-4.1.2 =uclibc-0.9.30.1-r1 bash make gzip bzip2 
unzip tar gnuconfig m4 sys-apps/texinfo gawk coreutils sed grep shadow procps net-tools iputils 
debianutils cpio attr sys-apps/acl kbd nano less diffutils

Vemos que instalamos las mismas versiones de binutils, gcc y uclibc que las usadas para generar la cadena de compilación cruzada. Instalamos coreutils y demás en lugar de busybox (o system) porque las utilidades de éste son versiones recortadas y dan problemas con algunas compilaciones. También instalamos tar, gnuconfig, m4 y texinfo, los cuales serán necesarios para instalar autoconf, automake y libtool. La razón de no instalar estos últimos directamente es que la instalación de Perl por compilación cruzada no funciona; tendremos que hacerlo luego a mano.

Por último, creamos los directorios /proc, /dev y /sys en /usr/mipsel-unknown-linux-uclibc, y ya podemos comprimir ese directorio utilizando

tar -cpvf buildchain.tar /usr/mipsel-unknown-linux-uclibc

copiarlo en el disco duro, en /tmp/hdd/volumes/HDD1, descomprimirlo, y lanzar un entorno de compilación utilizando este script, que automáticamente montará mediante bind los directorios del sistema y utilizará chroot para cambiar al nuevo entorno. Ahora nos bajamos Perl, lo descomprimimos y lo compilamos con

sh Configure -de
make
make install

Cabe recordar que el procesador de este disco duro es MUY LENTO, por lo que es posible que necesite toda la noche para compilarlo. Por otro lado, podemos tener problemas con las fechas de los archivos, por lo que es fundamental cambiarlas utilizando el comando touch * en cada directorio. Esto se puede hacer más cómodamente con la línea

find -type d -exec touch {}/* ;

que hará un touch * de manera recursiva en cada directorio. Una vez hecho esto, instalamos autoconf, automake y libtool (no olvidarse de touch en cada uno), y ya tendremos nuestro sistema de desarrollo completo con el que podremos compilar cualquier utilidad. Sólo hay que tener en cuenta algunos detalles:

  • El procesador del disco duro no es gran cosa, así que la compilación tarda BASTANTE tiempo
  • Es fundamental añadir la opción -static en las opciones de enlazado. En algunos programas es posible hacerlo añadiendo LDFLAGS=-static justo antes de ./configure (ejemplo: para configurar ctorrent, la línea sería LDFLAGS=-static ./configure); otra opción es lanzar primero ./configure y luego editar el Makefile para añadirlo donde se defina LDFLAGS. Como opción final, se puede compilar normalmente y, cuando termine, copiar y pegar las líneas de enlazado (suele ser la última) y añadir -static a mano antes de ejecutarla.
  • Es muy recomendable eliminar el parámetro -g durante la compilación, pues lo que hace es añadir información de depuración totalmente innecesaria, además de impedir que el compilador pueda aplicar muchas optimizaciones. Para hacer esto no queda más remedio que editar manualmente el fichero Makefile (no olvidar que puede haber varios Makefiles en otros subdirectorios. Hay que editarlos todos). También es bueno utilizar el comando strip en el ejecutable final para eliminar los últimos restos de datos de depuración
  • Algunos programas están preparados para versiones de autoconf o automake anteriores a la que hemos instalado. En ese caso basta con hacer un autoreconf para regenerar los ficheros. Este debe hacerse después de autogen.sh si lo hubiera. Una vez hecho esto ya se puede ejecutar ./configure y make.
  • Es necesario ajustar las fechas de los archivos porque, si no, Make se lía y no sabe qué compilar. Para ello basta con ejecutar el comando touch * en todos y cada uno de los directorios del programa a compilar (la línea find -type d -exec touch {}/* ; lo hará de manera recursiva por nosotros). No recomiendo cambiar la hora del disco duro porque, por alguna razón, las veces que lo hice el sistema se volvió inestable, llegando a colgarse incluso.
  • En algunos programas, libtool «se vuelve loco» y empieza a lanzar copias de sí mismo indiscriminadamente, llegando a ahogar al procesador y colgando el disco duro. Si, cuando va a enlazar el código, un PS nos devuelve una gran cantidad de procesos libtool, hay que matarlos rápidamente y enlazar «a mano» el código.

Para aquellos que no quieran pasar todo el trabajo, pueden bajarse el entorno de compilación completo aquí. Basta con descomprimir el .zip, copiar el .tar en el directorio /tmp/hdd/volumes/HDD1 del disco duro y descomprimirlo mediante

tar -xpvf buildchain_1.0.tar

entrar en el directorio con cd buildchain, montar los sistemas de archivos virtuales (proc, dev y sys) con ./mount.sh y lanzar un chroot con ./launch.sh. Una vez se haya terminado, salir y desmontar los sistemas de archivos virtuales con ./umount.sh.

FTP-ando

Actualizado; el enlace a los binarios estaba mal.Tras curiosear y probar, ya he conseguido meter un nuevo cliente de BitTorrent y un servidor de FTP en mi disco duro, aunque, por diversas razones (que comentaré en otra entrada), el código proviene de la página del MediaPlayer RTD1261, en lugar de haber sido compilado con la Gentoo que comentaba en entradas anteriores.

El nuevo servidor BitTorrent es cTorrent, junto con la interfaz web yodctcs. Respecto al servidor FTP, se trata de bftpd. Básicamente he retocado las configuraciones para que todo funcione sin tener que meter ficheros en carpetas del directorio raíz (por ejemplo, en /etc o en /lib). La razón es que, por defecto, toda esa parte (que está almacenada en la Flash) se monta en modo sólo-lectura; pero aunque pudiese escribir, sería bastante arriesgado (un error y tendré un caro pisapapeles), por lo que mi intención es hacer cualquier cambio únicamente en el disco duro, en donde se pueda recuperar todo simplemente ejecutando la opción de formateo desde el menú principal.

AVISO: a partir de aquí empiezo a tocar en el sistema operativo del disco duro multimedia, lo que significa que estas acciones sólo las deben realizar aquellos que sepan muy bien lo que hacen. Si alguien se carga su disco, será el único responsable.

Avisados estáis.

Lo primero es copiar el contenido del fichero con los binarios (este) en el disco duro multimedia, en concreto el fichero upgrade.tar. En él están todos los binarios y ficheros de configuración.

Una vez que lo tenemos (en /tmp/hdd/volumes/HDD1) entramos por telnet, lo movemos a /tmp/hdd/root y lo descomprimimos en esa carpeta con tar -xpvf upgrade.tar, de manera que se conserven los permisos de los ficheros. Dentro hay cuatro carpetas y un fichero script:

  • etc: contiene los ficheros de configuración del cliente BitTorrent y del servidor FTP
  • bftpd: contiene los binarios del servidor FTP
  • ctorrent: contiene los binarios del cliente BitTorrent cTorrent y de su interfaz web dctcs
  • lib: contiene las bibliotecas libgcc_s.so y libstdc++.so, necesarias para dctcs
  • btpd: reemplaza al script original.

El script btpd permite lanzar y parar todos los nuevos servicios de manera selectiva, relanzando aquellos procesos que queremos que estén lanzados si se caen, y matando los que no queremos si, por la razón que sea, se ejecutan (todo esto es posible porque el disco duro ejecuta regularmente este script, junto con el de samba, con el comando start). También monta, si se desea, la partición principal como EXT3. Por último, asigna a la variable de entorno LD_LIBRARY_PATH el valor /tmp/hdd/root/lib de manera que los programas lanzados desde él puedan utilizar las bibliotecas aunque éstas no se encuentren en los directorios por defecto (/lib, /usr/lib o /usr/local/lib). Es necesario editar este script (por ejemplo, con vi) para ajustar la configuración a nuestras necesidades. En concreto, si lo abrimos, vemos al principio lo siguiente:

# change here to set the services you want:
# 1: launch it
# 0: don't launch it

# main partition in EXT3 format
HD_EXT3=1

# old BitTorrent service
OLD_BT=0

# new BitTorrent service (cTorrent)
NEW_BT=1

# FTP server
FTP=1

Así, si queremos utilizar el cliente de BitTorrent original, tenemos que almacenar un 1 en OLD_BT. Si queremos utilizar el nuevo cliente BitTorrent, ponemos un 1 en NEW_BT. Si queremos activar el servidor FTP ponemos a 1 FTP. Y si hemos formateado en EXT3 la partición principal del disco duro, entonces tenemos que poner a 1 HD_EXT3 (si la tenemos en NTFS es imprescindible ponerla a 0). Una vez hecho esto, movemos dicho script a la carpeta script, reemplazando al viejo btpd. En el tar.bz2 incluyo la versión original, por si alguien se arrepiente.

Finalmente, lanzamos los nuevos programas mediante el comando ./btpd start y listo, ya tenemos acceso por FTP y un nuevo cliente BitTorrent.

Para acceder al cliente bittorrent hay que abrir con un navegador una conexión al puerto 8080 del disco duro multimedia. El usuario por defecto es admin, y la clave 123, pero se pueden cambiar editando el fichero /tmp/hdd/root/etc/dtcts.conf. Algunos cambios que hice en él con respecto al original de la página del otro disco duro fueron, por una parte, aumentar el buffer de recepción hasta 64Kbytes para conseguir la misma velocidad de transferencia (2,4MBytes/seg) que con SMB (con los 2Kbytes originales sólo se conseguían 200Kbytes/seg, diez veces más lento), así como eliminar toda la parte de registro (log) para no consumir disco duro inútilmente (quien quiera activarlo sólo tiene que echar un vistazo al fichero de configuración de demostración que viene en el paquete original de dtcts). Por último, cambié los nombres de las carpetas: en /tmp/hdd/volumes/HDD1/BT almacena los ficheros recibidos, igual que el viejo cliente BitTorrent, y en DOWNLOADS almacena los .torrent de los ficheros que se están descargando.

Respecto al servidor FTP, por defecto se puede entrar como anónimo, pero se puede cambiar la configuración en el fichero /tmp/hdd/root/etc/bftpd.conf.

Emergiendo

Actualizado. Hace unos días encontré una página sobre discos duros multimedia basados en procesador MIPS. Aunque no es sobre el mismo modelo que mi disco, sí tiene cosas lo suficientemente parecidas como para que funcione. Una de ellas es la idea de utilizar una Debian para MIPS mediante chroot para poder añadir cosas extra.

Aunque la idea es buena, por cuestiones personales prefería utilizar Gentoo, así que me bajé la stage3 para MIPS, la copié en el disco duro e intenté hacer un chroot. Pero como siempre, las cosas nunca son sencillas: decía que no podía ejecutar bash. Extrañado, copié el ejecutable a mi equipo de sobremesa y lo analicé con GHex, comparándolo con el ejecutable de BusyBox.

El problema resultó ser que los stages de Gentoo para MIPS están en formato big-endian, mientras que mi disco duro trabaja en little-endian (parece ser que los procesadores MIPS, aunque pueden trabajar con ambos formatos, no pueden utilizarlos a la vez, sino que se escoge a nivel hardware durante el arranque). Cuando un sistema trabaja en little-endian se dice que es un MIPSel.

Rebuscando encontré unos stages para MIPSel, pero eran del año 2005. Intenté usarlos y, aunque funcionaban, en cuanto intentaba actualizar el sistema al más reciente, fallaba (todo apuntaba a la versión de python, que era demasiado vieja para ejecutar el último portage). Seguí buscando y encontré que las estaciones de trabajo Cobalt trabajaban en little-endian, así que probé de nuevo con unos stages diseñados para ellas, pero seguía fallando.

Decidí entonces probar con la Debian de la página inicial, pero al hacer un dist-upgrade volvía a fallar.

Ante esto, decidí que sólo tenía dos opciones: o utilizaba sólo cross-compiling, o intentaba generar yo mismo un stage de Gentoo para MIPSel. Como no podía ser de otra manera, tiré por la segunda 🙂 Por supuesto, es la primera vez que lo hago, así que, aunque me ha funcionado, puede ser que haya metido la pata en algo, o que alguna cosa se pueda hacer mejor, así que los comentarios están abiertos para cualquier sugerencia o corrección.

AVISO: a partir de aquí empiezo a tocar en el sistema operativo del disco duro multimedia, lo que significa que estas acciones sólo las deben realizar aquellos que sepan muy bien lo que hacen. Si alguien se carga su disco, será el único responsable.

Avisados estáis.

Lo primero que hice fue instalar una Gentoo para x86 en mi sistema. Pero como no quería formatear mi actual Ubuntu, decidí hacer una instalación virtual. Veamos como:

Para empezar, descargamos las versiones más recientes del stage3 y el portage de Gentoo, y las descomprimimos en un directorio (el portage se descomprime dentro del directorio /usr del stage3), en mi caso llamado gentoo:

mkdir /home/raster/gentoo
sudo tar -xjvf stage3-i686-20090915.tar.bz2 -C /home/raster/gentoo/
sudo tar -xjvf portage-lastest.tar.bz2 -C /home/raster/gentoo/usr/

La razón de utilizar sudo es que, si no, no podrá crear algunos ficheros especiales en el directorio.

A continuación montamos una copia de los sistemas de archivos especiales de Linux (/proc, /dev, /dev/pts y /sys), además de copiar el fichero resolv.conf para poder conectarnos a Internet. Sin ellos no podríamos hacer muchas cosas básicas:

sudo mount -o bind /proc /home/raster/gentoo/proc
sudo mount -o bind /dev /home/raster/gentoo/dev
sudo mount -o bind /dev/pts /home/raster/gentoo/dev/pts
sudo mount -o bind /sys /home/raster/gentoo/sys
sudo cp /etc/resolv.conf /home/raster/gentoo/etc/resolv.conf

Notar el parámetro -o bind en mount: lo que hace es coger un sistema de archivos ya montado y montarlo también en el nuevo directorio, de manera que esté disponible en ambos a la vez.

Por último, hacemos un chroot para entrar en el sistema:

sudo chroot /home/raster/gentoo/ /bin/bash

Ya estamos dentro de nuestra Gentoo, pero antes de empezar tenemos que cargar el entorno:

env-update
source /etc/profile

Con ésto ya podemos empezar a trabajar. Lo primero es actualizar todo el sistema a los últimos paquetes, para lo que hacemos:

emerge --sync
emerge --update --deep world

Y ya podemos empezar a crear nuestro stage. Lo primero es instalar crossdev, un paquete que automatiza la generación de entornos de compilación cruzada (la documentación oficial está aquí y aquí):

emerge portage-utils crossdev

A continuación, editamos el fichero /etc/make.conf y añadimos la línea PORTDIR_OVERLAY=/usr/local/portage (podemos utilizar el editor nano, o vi) y, opcionalmente, la línea MAKEOPTS=»-jX» (siendo X el número de procesadores más 1; yo, como tengo un doble núcleo, uso -j3). Por último, creamos el directorio /usr/local/portage, y ya podemos generar un compilador para MIPSel, linux, y uclibc:

crossdev -v --target mipsel-unknown-linux-uclibc

Las distintas combinaciones de procesadores, núcleos y bibliotecas están en la documentación de crossdev, en una tabla.

Se tirará un buen rato compilando, tras el cual podemos comprobar si todo fue correctamente con:

gcc-config -l

En mi caso devuelve:

[1] i686-pc-linux-gnu-4.3.2 *
[2] mipsel-unknown-linux-uclibc-4.3.4 *

Con este toolchain podremos compilar cosas de manera nativa pra el disco duro. Para probarlo escribimos el típico Hola mundo y lo compilamos con:

mipsel-unknown-linux-uclibc-gcc -o holamundo holamundo.c

lo copiamos al disco duro multimedia y probamos a ejecutarlo. Debería funcionar a la primera.

Una vez que tenemos el toolchain para compilación cruzada, vamos a crear nuestra stage. Para ello tenemos que instalar el paquete crossdev-wrappers, tal y como se explica en su página, e inicializarlo. Por desgracia, por defecto está enmascarado, así que tenemos que desenmascararlo para que podamos instalarlo. Para ello escribimos:

echo "sys-devel/crossdev-wrappers ~* *" >> /etc/portage/package.keywords/i686-unknown-linux-gnu

Asumiendo, por supuesto, que /etc/portage/package.keywords es un directorio. Si es un fichero, entontes sería

echo "sys-devel/crossdev-wrappers ~* *" >> /etc/portage/package.keywords

Ahora ya podemos instalar crossdev-wrappers:

emerge crossdev-wrappers
emerge-wrapper --init

Este paquete nos permite instalar cualquier paquete de Gentoo, pero compilándolo para el sistema para el que tenemos compilador cruzado, e instalando el sistema de archivos en un directorio aparte (por defecto en /usr/arquitectura; o sea, /usr/mipsel-unknown-linux-uclibc en este caso), que podremos comprimir con tar e instalar en el sistema destino. Pero antes de empezar a utilizarlo tenemos que configurarlo adecuadamente. Lo primero es editar el fichero /usr/mipsel-unknown-linux-uclibc/etc/make.conf y ajustarlo a nuestros intereses. En mi caso, por defecto estaba así:

CHOST=mipsel-unknown-linux-uclibc
CBUILD=i686-pc-linux-gnu
ARCH=mips

HOSTCC=i686-pc-linux-gnu-gcc
E_MACHINE=EM_MIPS

ROOT=/usr/${CHOST}/

ACCEPT_KEYWORDS="mips ~mips"

USE="${ARCH} zlib bindist make-symlinks minimal"

#MARCH_TUNE="-march=armv4t -mtune=arm9tdmi"     #arm-softfloat-linux-uclibc
#MARCH_TUNE="-march=armv5t -mtune=xscale"       #armv5teb-softfloat-linux-gnueabi

CFLAGS="-Os -pipe ${MARCH_TUNE} -fomit-frame-pointer -I${ROOT}usr/include/ -I${ROOT}include/"
CXXFLAGS="${CFLAGS}"
LDFLAGS="-L${ROOT}lib -L${ROOT}usr/lib"

FEATURES="-collision-protect sandbox buildpkg noman noinfo nodoc"
# Be sure we dont overwrite pkgs from another repo..
PKGDIR=${ROOT}packages/
PORTAGE_TMPDIR=${ROOT}tmp/

ELIBC="glibc"

PKG_CONFIG_PATH="${ROOT}usr/lib/pkgconfig/"
#PORTDIR_OVERLAY="/usr/portage/local/"

LIBDIR_${ARCH}="lib"
LIBDIR_amd64=lib64
MAKEOPTS=-j2

Hay varios cambios a realizar. Para empezar, hay que añadir MARCH_TUNE=»-march=4kec», de manera que optimicemos para el procesador específico de mi disco duro (esto hay que cambiarlo para el modelo específico del procesador del disco duro que se quiera utilizar). Por otro lado, hay que cambiar MAKEOPTS=-j2 por MAKEOPTS=-j3, porque yo tengo dos núcleos. Al final tenemos:

CHOST=mipsel-unknown-linux-uclibc
CBUILD=i686-pc-linux-gnu
ARCH=mips
MARCH_TUNE="-march=4kec"

HOSTCC=i686-pc-linux-gnu-gcc
E_MACHINE=EM_MIPS

ROOT=/usr/${CHOST}/

ACCEPT_KEYWORDS="mips ~mips"

USE="${ARCH} zlib bindist make-symlinks minimal"

CFLAGS="-Os -pipe ${MARCH_TUNE} -fomit-frame-pointer -I${ROOT}usr/include/ -I${ROOT}include/"
CXXFLAGS="${CFLAGS}"
LDFLAGS="-L${ROOT}lib -L${ROOT}usr/lib"

FEATURES="-collision-protect sandbox buildpkg noman noinfo nodoc"
# Be sure we dont overwrite pkgs from another repo..
PKGDIR=${ROOT}packages/
PORTAGE_TMPDIR=${ROOT}tmp/

ELIBC="glibc"

PKG_CONFIG_PATH="${ROOT}usr/lib/pkgconfig/"
#PORTDIR_OVERLAY="/usr/local/portage"

LIBDIR_${ARCH}="lib"
LIBDIR_amd64=lib64
MAKEOPTS=-j3

También hay que ajustar el perfil deseado. Por defecto nos ha puesto embedded, que es perfecto para nuestro caso; pero si queremos cambiarlo basta con borrar /usr/mipsel-unknown-linux-uclibc/etc/make.profile y enlazarlo al perfil deseado de los disponibles en /usr/portage/profiles.

Y ya sólo queda por compilar todos los paquetes que queramos, utilizando el comando emerge-mipsel-unknown-linux-uclibc. Así, el primero que, probablemente, queramos instalar será system.

emerge-mipsel-unknown-linux-uclibc system

que instalará BusyBox con todas las librerías de uClinux. Una vez hecho esto sólo tenemos que crear los directorios que faltan con:

cd /usr/mipsel-unknown-linux-uclibc
mkdir dev proc root sys

y ya tendremos un sistema de ficheros que podremos probar. Para ello basta con empaquetarlo con tar (no comprimirlo, porque al menos mi disco duro no tiene ni gzip ni bzip2), descomprimirlo en el disco duro, montar proc, dev, dev/pts y sys como al principio de esta entrada, copiar /etc/resolv.conf y hacer un chroot, aunque esta vez con /bin/ash, porque busybox no dispone de bash.

Otra cosa que podemos hacer es añadir en/usr/mipsel-unknown-linux-uclibc/etc/make.conf una línea USE con las opciones que nos interesen de cara a compilar (opciones que se pueden consultar aquí).

Tuneando discos

Esta semana hice varias pruebas del disco duro. Para empezar, probé varios formatos diferentes, y el resultado es que DivX lo soporta perfectamente, en SD, HD y FullHD. Parece que en FullHD (probado con Big Buck Bunny) se atasca una pizca en algún que otro momento, mientras que en HD y SD va todo como la seda.

Sin embargo, probé a cambiar el sistema de archivos por EXT3 en lugar de NTFS y parece que los atascos han desaparecido.

Respecto al tema de que se encendiese él sólo al encender la luz del salón, lo he solucionado cambiando la bombilla por otra de otra marca.

Formatear la partición de EXT3

Las razones por las que he cambiado la partición principal a EXT3 son dos: por una parte me da más confianza ese sistema porque, a fin de cuentas, es nativo de Linux y se conoce perfectamente, mientras que NTFS es un sistema que se conoce por ingeniería inversa; por otro lado, parece que consigo una pizca más de rendimiento (2,2MB/seg frente a 2,0MB/seg de NTFS), lo que deduzco que es lo que elimina los pequeños tirones que se notaban al reproducir DivX en FullHD.

AVISO: a partir de aquí empiezo a tocar en el sistema operativo del disco duro multimedia, lo que significa que estas acciones sólo las deben realizar aquellos que sepan muy bien lo que hacen. Si alguien se carga su disco, será el único responsable.

Avisados estáis.

Para cambiar el sistema de archivos basta con seguir los siguientes pasos:

Si echamos un vistazo a como están montadas las particiones, vemos lo siguiente:

/ # mount
/dev/root on / type squashfs (ro)
none on /dev type devfs (rw)
none on /proc type proc (rw,nodiratime)
devpts on /dev/pts type devpts (rw)
none on /sys type sysfs (rw)
/dev/mtdblock/2 on /usr/local/etc type jffs2 (rw,noatime)
none on /tmp type ramfs (rw)
/dev/rd/0 on /mnt/rd type vfat (rw,nodiratime,fmask=0022,dmask=0022,codepage=cp437,iocharset=iso8859-1)
/dev/ide/host0/bus0/target0/lun0/part2 on /tmp/hdd/root type ext3 (rw)
/dev/ide/host0/bus0/target0/lun0/part3 on /tmp/hdd/volumes/HDD1 type NTFS (rw)

La partición /dev/ide/host0/bus0/target0/lun0/part2 (/dev/hda2) contiene parte del sistema operativo; en concreto los módulos SMB para acceso por red y el cliente bittorrent, mientras que /dev/ide/host0/bus0/target0/lun0/part3 (/dev/hda3) contiene la partición visible desde el exterior.

Antes de nada copiamos a otro lado todos los ficheros que tengamos en el disco (pues se borrará todo lo que contenga), desmontamos la partición, formateamos en EXT3, volvemos a montarla y creamos el directorio BT:

umount /tmp/hdd/volumes/HDD1
mke2fs -j /dev/ide/host0/bus0/target0/lun0/part3
mount /dev/ide/host0/bus0/target0/lun0/part3 /tmp/hdd/volumes/HDD1
mkdir /tmp/hdd/volumes/HDD1/BT

Vemos que, si apagamos el disco y lo volvemos a encender, la partición sigue montada, lo que parece sugerir que el sistema es capaz de montarla sea del tipo que sea. Por desgracia, en realidad esto no es así: cuando le damos al botón de apagado, el disco se hiberna en lugar de apagarse, por lo que, cuando se enciende, no arranca desde el principio sino que vuelve al estado en que estaba cuando se apagó. Sin embargo, si lo apagamos «de verdad» (por ejemplo desenchufándolo de la red eléctrica, o porque se va la luz), entonces, cuando volvamos a encenderlo, veremos que no ha montado la partición en EXT3.

Para solucionarlo vamos a modificar los scripts de arranque para que monte la partición automáticamente si es necesario. Para ello nos vamos a /tmp/hdd/root/scripts y vemos que hay varios ficheros. Nos interesan uno de éstos: o btpd o samba. Estos scripts se lanzan durante el arranque para arrancar los servicios de BitTorrent y Samba. En principio podría parecer que basta con añadir un nuevo script para que lo ejecute, pero no lo es: sólo ejecuta esos scripts durante el arranque. Así pues, lo que haremos será modificar uno de ellos para que, al encender el equipo, monte la partición correspondiente. Para ello editamos, utilizando vi, uno de ellos y añadimos al principio las líneas:

if [ -e "/tmp/hdd/volumes/HDD1/lost+found" ]
then
    echo "Particion EXT3 ya montada"
else
    mount /dev/ide/host0/bus0/target0/lun0/part3 /tmp/hdd/volumes/HDD1
    echo "Montando particion EXT3"
fi

Este código comprobará si existe el directorio /tmp/hdd/volumes/HDD1/lost+found (que siempre existe en cualquier partición EXT3), en cuyo caso la partición estará montada y no hará nada; pero si no existe, entonces es que no está montada, así que procederá a hacerlo.

La próxima entrada espero empezar a intentar programar cosas para él.

Multimediando

Paseando por un centro comercial cualquiera acabé dentro de una cadena de electrodomésticos cualquiera, en la que había un interesante disco duro multimedia de 1 tera con conexión de red y bittorrent integrado: un MemUp LX Series. Por si fuera poco anunciaban que soportaba MKV y H.264 en FullHD, con lo que no me lo pensé y me lo compré. Luego resultó que esos dos formatos sólo los soporta si pones un ordenador a trascodificar para que le envíe los datos masticados por red, pero aún así, el cliente bittorrent integrado tenía buena pinta. Además, con suerte usaría un Linux embebido (empotrado siempre me sonó mal 🙂 ), con lo que incluso era posible que pudiese hacerle modificaciones. Y aunque no fuese así, al menos podría ver mis series favoritas en la tele sin tener que andar de un lado para otro con un DVD regrabable.

La primera prueba, reproducir un DivX, fue excelente: buena calidad de imagen y sonido, buenos menús (incluso tiene una previsualización y todo)… buena pinta. El acceso por red, por su parte, lo considero simplemente aceptable: es por SMB (red de windows), lo que no me convence mucho porque, aunque una vez que has entrado funciona bien, a veces da algún problemilla, así que añadir un servidor FTP sería una buena idea.

Por desgracia, en cuanto intenté usar el cliente BitTorrent desde la (espartana) interfaz web, empezaron los problemas: la descarga no arrancaba, e incluso el aparato se colgaba en según qué momentos (!). Un poco mosca, decidí dejar de lado el cliente BT de momento e investigar por otro lado a ver qué descubría.

AVISO: a partir de aquí empiezo a tocar en el sistema operativo del disco duro multimedia, lo que significa que estas acciones sólo las deben realizar aquellos que sepan muy bien lo que hacen. Si alguien se carga su disco, será el único responsable.

Avisados estáis.

Comencé con un escaneo de puertos, y apareció nada menos que un servicio de telnet. La cosa se ponía interesante. Me conecté, puse root como usuario, y p’adentro, sin clave ni nada (así da gusto). Lo primero que hice fue echar un vistazo a /proc/version, /proc/cpuinfo y /proc/meminfo, que devolvieron lo siguiente (he marcado en rojo las partes interesantes):

Trying 192.168.1.103...
Connected to 192.168.1.103.
Escape character is '^]'.
Venus login: root
warning: cannot change to home directory

BusyBox v1.1.3 (2008.12.15-01:58+0000) Built-in shell (ash)
Enter 'help' for a list of built-in commands.

/ # cat /proc/version
Linux version 2.6.12.6-VENUS (root@localhost.localdomain) (gcc version 3.4.4 mipssde-6.03.01-20051114) #13 Mon Mar 9 14:40:01 CST 2009

/ # cat /proc/cpuinfo
system type             : Realtek Venus
processor               : 0
cpu model               : MIPS 4KEc V6.4
BogoMIPS                : 199.06
wait instruction        : yes
microsecond timers      : yes
tlb_entries             : 16
extra interrupt vector  : yes
hardware watchpoint     : yes
ASEs implemented        :
VCED exceptions         : not available
VCEI exceptions         : not available

/ # cat /proc/meminfo
MemTotal:        56984 kB
MemFree:          9460 kB
Buffers:           760 kB
Cached:           6436 kB
SwapCached:          0 kB
Active:           6812 kB
Inactive:         2976 kB
HighTotal:           0 kB
HighFree:            0 kB
LowTotal:        56984 kB
LowFree:          9460 kB
SwapTotal:          32 kB
SwapFree:           32 kB
Dirty:               0 kB
Writeback:           0 kB
Mapped:           7208 kB
Slab:             3476 kB
CommitLimit:     28524 kB
Committed_AS:     7848 kB
PageTables:        368 kB
VmallocTotal:  1048560 kB
VmallocUsed:       696 kB
VmallocChunk:  1047804 kB

¡Sí, un Linux con entorno BusyBox! Eso simplificaba mucho las cosas. Por otra parte, un procesador MIPS es buena cosa también. Habría sido mejor un ARM, sin duda, pero éste también está bastante bien soportado. Sin embargo, lo que no me cuadraba era la memoria: ¿sólo 57MB de RAM y sin Swap? Un poco raro. De hecho, esa falta de memoria podría tener algo que ver con los cuelgues.

Al principio sospeché que el sistema podría ser un uClinux, el cual, al ser para sistemas sin MMU, no puede utilizar Swap. Pero por otro lado, hasta donde yo sabía, todos los micros MIPS llevan gestor de memoria, por lo que no tenía mucho sentido.

Decidí echar un vistazo al sistema de archivos para ver si podría probar a crear una partición de Swap que aliviase el escaso margen de memoria, y entonces apareció la segunda sorpresa:

/ # fdisk /dev/hda

The number of cylinders for this disk is set to 121601.
There is nothing wrong with that, but this is larger than 1024,
and could in certain setups cause problems with:
1) software that runs at boot time (e.g., old versions of LILO)
2) booting and partitioning software from other OSs
 (e.g., DOS FDISK, OS/2 FDISK)

Command (m for help): p

Disk /dev/hda: 1000.2 GB, 1000204886016 bytes
255 heads, 63 sectors/track, 121601 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

 Device Boot    Start       End    Blocks   Id  System
/dev/hda1               2          21      160650   82  Linux swap
/dev/hda2              22          41      160650   83  Linux
/dev/hda3              42      121581   976270050    7  HPFS/NTFS

¡Ya había una partición de Swap definida! ¿Pero por qué no la usaba? Probé a activarla a mano con swapon /dev/hda1 pero sólo conseguí un mensaje de error. Sospechando que algo raro pasaba con ella, decidí hacer un volcado a mi ordenador de sobremesa y examinarla con Ghex2 (un editor hexadecimal) para ver qué contenía, no fuese a ser una partición de datos con un tipo incorrecto. La sorpresa fue mayúscula cuando descubrí ¡que estaba completamente a cero! La partición de Swap no estaba formateada, y por eso no la reconocía el sistema como tal.

Mi primer impulso fue formatearla manualmente, pero entonces recordé que en el menú Ajustes -> Sistema había una opción para formatear el disco. Decidí probarla a ver si también hacía algo con ésta, y así fue: después de ordenar el formateo desde el menú del disco multimedia, no sólo se borró la partición principal, sino que formateó también la partición de Swap y la montó correctamente. Sin embargo, la interfaz web había desaparecido, y en su lugar sólo aparecía una página de demostración de CGIs.

¿Qué había pasado? Nada más terminar de formatear, el disco pregunta si queremos instalar BT/SAMBA, y nos da cinco escasos segundos para pulsar OK si queremos hacerlo. Yo me despisté, el temporizador venció, y no instaló nada. Así que decidí formatearlo de nuevo y esta vez estuve atento para pulsar el OK en el momento adecuado. Una vez hecho todo quedó perfecto: la interfaz Web apareció y el cliente BitTorrent funcionó perfectamente, sin cuelgues.

Así pues, si teneis un disco de este tipo y os da problemas, probad a formatearlo desde el menú principal. Con un poco de suerte puede ser que se solucione (pero no os olvidéis de copiar antes los archivos que tuvieseis en el disco duro multimedia, ya que se perderán por completo durante el formateo).

Dado que la entrada me está saliendo algo larga pararé aquí y seguiré con mis descubrimientos sobre el sistema de archivos, el entorno de desarrollo y otras hierbas en otra entrada.