miércoles, 27 de febrero de 2013

Desarrollo de Firmware para dispositivos embebidos, con GNU/Linux OpenWRT

En este Espacio iré documentando y actualizando las conclusiones y experiencias que tendré en el proceso de ir aprendiendo a implementar, customizar y desarrollar firmware para dispositivos embedidos, especialmente Router inalámbricos.
Se empezará con cuestiones básicas, y siempre siguiendo ejemplos reales. Para temas mas profundos que espero abordar, recomiendo ir directamente a la documentación de OpenWRT:

http://kamikaze.openwrt.org/docs/openwrt.html

La primera parte de este blog es la que ya habia desarrollado en www.ricb.org, escrito por Andres Gomez de la RICB y Jorge Gonzalez de Zoociedad, para la democratización de documentación en español sobre OpenWRT.

********

Que es OpenWrt ?

De Wikipedia : OpenWRT es una distribución de Linux basada en firmware usada para dispositivos empotrados tales como routers personales.
El desarrollo de OpenWRT fue impulsado inicialmente gracias a la licencia GPL y su carácter vírico, que impulsaba a todos aquellos fabricantes que modificaban y mejoraban el código, a liberar éste y contribuir cada vez más al proyecto en general. Poco a poco el software ha ido creciendo y se encuentran características implementadas que no tienen muchos otros fabricantes de dispositivos comerciales para el sector no profesional, tales como QoS, VPN y otras características que dotan a OpenWRT de un dispositivo realmente potente y versátil, apto para utilizar los hardware donde corre OpenWRT no sólo para utilizarlos como routers, sino como servidores de archivo, nodos P2P, servidores de WEBcams, firewall o puertas de acceso VPN.

OpenWRT tiene varias versiones de desarrollo. En esta guia se usará la versión en constante desarrollo llamada "trunk".

¿ Porque crear una imagen propia del OpenWrt?

El Slogan de OpenWrt nos da una primera idea: "WIRELESS FREEDOM".
El programador experimental encontrará en OpenWrt un sistema operativo de código Abierto para sistemas embebidos WIFI, muy completo, documentado y avanzado; como todo Software Libre, podrá modificarlo, estudiarlo, adaptarlo y así crear su distribución personalizada.
Quien quiere expermimentar con OpenWrt encontrará la libertad de los routers inalámbricos, tendrá a mano todas las opciones para hacer de éstas máquinas casi cualquier cosa; ventajas del software libre y la difusión del conocimiento que la visión mercantilista y privada no permite.
Se puede personalizar un Router Inalámbrico para que haga cosas como: streaming de audio, streaming de video, uso de archivos de una USB, uso de discos duros, montaje de servidores FTP, P2P, servidores web, de correo, etc.,.... Solamente se personaliza OpenWrt y se crea una imagen.... el nuevo firmware del router.
Nuestra motivación particular e inicial es modificar un router y poder utilziarlo para correr protocolos de enrutamiento que nos permitan crear una red Mesh, donde muchos nodos se interconceten y haya eficiencia en la comunicación de paquetes, que en la práctica redundará en una gran red con acceso a muchos nodos y clietes comunitarios.

MANUAL OpenWrt

Inicialmente este manual está basado en el publicado en la página oficial de OpenWrt y en su puesta en práctica:
http://wiki.openwrt.org/inbox/howto.build.openwrt
Aunque este manual es más extenso y prentende responder todas las preguntas que en la práctica surgieron y que muchas otras que pudieran surgir.
A continuación se explican diversos procedimientos que nos permitirán al final desarrollar un firmware para los router inalámbircos, que esten personalizados de acuerdo a nuestras necesidades.
NOTA!!!! CONVENCIONES - ANTES DE EMPEZAR
Debido a que se incluirán muchos códigos se adopta las siguientes onvenciones para evitar confusiones:

Código con fondo blanco: Comandos en consola de Linux, a insertar por el usuario.
Código con fondo azúl: Mensajes en consola de Linux, generados por el PC.
Código con fondo verde: Comandos en consola de OpenWrt, a insertar por el usuario.

Dispositivos Soportados

Como se dijo en "Que es OpenWrt?" muchas personas han trabajado altruistamente para que cada vez más dispositivos puedan trabajar con OpenWrt. Si ya se ha adquirido un Router en específico o se va a adquirir, aquí está la lista de dispositivos soportados, organizados por marca (fabricante):

http://wiki.openwrt.org/oldwiki/tableofhardware

Aunque el dispositivo estrella para OpenWrt es el Router Linksys WRT54G, vamos a experimentar con el Router Ubiquiti Nanostation 2, Nanostation M2, Unifi, etc...

Creacion de una imagen de OpenWrt

Pasos previos

  1. Tener un sistema adecuado para construir la imagen de OpenWrt
  2. Asegurarse que las dependencias necesarias están instaladas
  3. Copiar el código fuente del OpenWrt
Para lograr cada uno de estos pasos tenemos:

Sistema adecuado

Cuando se dice "tener un sistema adecuado" se refiere al sistema operativo donde podamos correr el ambiente de desarrollo del OpenWrt.
Debido a que OpenWrt es un proyecto esencialmente desarrollado bajo plataformas libres de GNU/Linux, el sistema operativo ideal para trabajar con OpenWrt es éste, GNU/Linux.
Este manual se desarrolla con base a una distribución de linux basada en Debian, así si tienes Ubuntu instalado, te sirve este manual.

Dependencias

Haciendo uso de la consola y sistema de comandos de Debian.
Actualización de repositorios: es importante que habitualmente se actualicen los repositorios. Recordar que los repositorios son almacenamientos centralizados de archivos donde encontramos todas las actualizaciones pertientes de los aplicactivos que se haya instalado (y del sistema en general), por ejemplo en Ubuntu, y también se encuentran todos los paquetes para instalación de nuevos aplicativos. Cuando instalamos un programa usando la consola de Linux o los gestores de paquetes como el Synaptic, se hacen requerimientos de paquetes a los repostiorios
Para dicha actualización simplemente en la consola de linux usamos los comandos:

 sudo apt-get update

Pon la clave de root y listo.

Las dependencias necesarias son compiladores, aplicaciones descomprimidas, librerías específicas, etc., Se hace esto para alistar el sistema y que pueda generar el ambiente de desarrollo del OpenWrt y pueda luego compilar la imagen.

En la consola:
 
sudo apt-get install g++ libncurses5-dev zlib1g-dev bison flex unzip autoconf gawk make gettext gcc 
binutils patch bzip2 libz-dev libc6-dev linux-headers-2.6.28-15 

Se debe generar un informe algo así:
 
Checking 'working-make'... ok. <br>
Checking 'case-sensitive-fs'... ok. <br>
Checking 'getopt'... ok. <br>
Checking 'fileutils'... ok. <br>
Checking 'working-gcc'... ok. <br>
Checking 'working-g++'... ok. <br>
Checking 'ncurses'... failed. <br>
Checking 'zlib'... ok. <br>
Checking 'gawk'... failed. <br>
Checking 'flex'... failed. <br>
Checking 'unzip'... ok. <br>
Checking 'bzip2'... ok. <br>
Checking 'patch'... failed. <br>
Checking 'perl'... ok. <br>
Checking 'python'... ok. <br>
Checking 'wget'... ok. <br>
Checking 'gnutar'... ok. <br>
Checking 'svn'... ok. <br>
Checking 'gnu-find'... ok. <br>
Checking 'getopt-extended'... ok. <br>
Checking 'non-root'... ok. <br>
Build dependency: Please install ncurses. (Missing libncurses.so or ncurses.h) <br>
Build dependency: Please install GNU awk. <br>
Build dependency: Please install flex. <br>
Build dependency: Please install patch. <br>
Prerequisite check failed. Use FORCE=1 to override. <br>
make: *** [tmp/.prereq-build] Error 1 

Como se puede observar en este caso muestra la verificación de los paquetes necesario, y hay unos que han fallado (failed); para poder continuar se necesita que este reporte verifique todo en "ok". Para lograr esto, el mismo sistema nos dice que necesitamos instalr unos paquetes.

En este caso vemos que falló la revisión de ncurses, gawkm, flex; lo arreglamos simplemente con
 
sudo apt-get install gawk
sudo apt-get install flex

Para el paquete ncurses fue necesario
 
sudo apt-get install libncurses5-dev

Cualquier duda con un paquete o un error, simplemente se consulta en Google, por ejemplo si aparece fallido el paquete "flex", se puede buscar en Google "instalar flex en debian" o "instalar flex en ubuntu".

Codigo fuente OpenWRT

Open Wrt dispone el código fuente completo de todo el sistema operativo. El siguiente paso, luego de haber alistastado el sistema es descargar este código para poder modificarlo con el entorno de configuración y luego compilarlo.
Para descargar toda la lista de archivos que compone le código del OpenWrt es nececsatio tener instalado el aplicativo Subversion

Instalar Subversion

  • ¿que es subversion?
Subversion, o SVN, es la versión actual del sistema de control usado por el proyecto OpenWrt.

Instalamos Subversion mediante consola:
 
 sudo apt-get install subversion

Luego de haber instalado el aplicativo, procedemos a crear una carpeta donde descargaremos el código fuente de OpenWrt y allí mismo se compila.
Recomendamos crear una carpeta en el directorio /home/[tu usuario]/

Puedes hacerlo en entorno gráfico con el explorador Nautilus o mediante consola navegando en el comando cd
 
cd ..

para crear la carpeta "OpenWrt"
 
mkdir OpenWrt 

ingresa a ella
 
 cd OpenWrt/ 

Descargar código fuente del OpenWrt

Hay varias versiones de OpenWRT, puedes ver como bajar cada una aqui;:

https://dev.openwrt.org/wiki/GetSource
A este momento, la vesrion de desarrollo es la "trunk" y se bajaria con  

 svn co svn://svn.openwrt.org/openwrt/trunk/

 
Nota opcional: Si te interesan otras versiones, como la Backfire la puedes bajar con instrucciones como: svn co svn://svn.openwrt.org/openwrt/branches/backfire
 
 

 Se empezará a desgar el código, mostrando algo así en el proceso:
A    trunk/toolchain/gcc
A    trunk/toolchain/gcc/files
A    trunk/toolchain/gcc/files/alternate-arch-cc.in
A    trunk/toolchain/gcc/patches
A    trunk/toolchain/gcc/patches/4.1.2
A    trunk/toolchain/gcc/patches/4.1.2/100-uclibc-conf.patch
A    trunk/toolchain/gcc/patches/4.1.2/300-libstdc++-pic.patch
A    trunk/toolchain/gcc/patches/4.1.2/120-cris-do_not_overide_limits_h_test.patch
A    trunk/toolchain/gcc/patches/4.1.2/910-soft-float.patch
A    trunk/toolchain/gcc/patches/4.1.2/802-fix-ICE-in-arm_unwind_emit_set.patch
A    trunk/toolchain/gcc/patches/4.1.2/304-index_macro.patch
A    trunk/toolchain/gcc/patches/4.1.2/200-uclibc-locale.patch
A    trunk/toolchain/gcc/patches/4.1.2/303-c99-complex-ugly-hack.patch

 Al descargar el Código creará una carpeta
TRUNK </b> dentro de la carpeta OpenWrt donde estará contenido todo el cídigo.
/home/"tu usuario"/OpenWrt/trunk


Procedimiento general:
  1. Verificar nuevamente la lista "trunk" usando Subversion
  2. Actualizar los paquetes (comando ./scripts/feeds update)
  3. Construir la configuración (comando make defconfig)
  4. Paquetes Symlink y el entorno de desarrollo
  5. Configurar la imagen a compilar (comando make menuconfig)
  6. Compilar (comando make)

Actualizaciones

Recuerda que hay mucha gente trabajando en los proyectos de software libre como OpenWrt y su código se mejora muy rápido, para asegurarte que se tiene la última versión del código fuente:

Ingresa a la carpeta OpenWrt
 
 cd trunk 

Y ejecuta el comando:
 
 svn up 

Esto genera algo así:
A    package/dnsmasq/patches/001-upstream-security.patch
U    package/dnsmasq/Makefile
Actualizado a la revisión 17464.

Actualizar ambiente desarrollo

Luego de actualizar el código fuente es necesario actualizar el ambiente de desarrollo (es decir los paquetes que permiten configurar, compilar, etc.).
 ./scripts/feeds update 
Esto genera algo así:
...
A    feeds/xwrt/webif-iw-lua-mesh-hotspot-freeradius/files/etc/config/iw_hotspot_wizard
A    feeds/xwrt/webif-iw-lua-mesh-hotspot-freeradius/ipkg
...
Updating feed 'luci' from 'http://svn.luci.subsignal.org/luci/tags/0.8.7/contrib/package' 
...
A    feeds/luci/olsrd-luci/ipkg
A    feeds/luci/olsrd-luci/ipkg/postinst
A    feeds/luci/olsrd-luci/Makefile
U   feeds/luci
Revisión obtenida: 5317
Create index file './feeds/luci.index' 
Collecting package info: done

Configuración nuevo sistema

El siguiente paso es generar una configuración general del sistema y configuración de la imagen, esto incluye una revisión de las dependencias, etc.
 make defconfig 
Esto debe generar algo así:
Checking 'working-make'... ok.
Checking 'case-sensitive-fs'... ok.
Checking 'getopt'... ok.
Checking 'fileutils'... ok.
Checking 'working-gcc'... ok.
Checking 'working-g++'... ok.
Checking 'ncurses'... failed.
Checking 'zlib'... ok.
Checking 'gawk'... failed.
Checking 'flex'... failed.
Checking 'unzip'... ok.
Checking 'bzip2'... ok.
Como se ve, nuevamente verifica las dependencias, si se instalaron adecuadamente en el primer procedimiento todo debe generar "OK", pero si aparece un error al ejecutar el comando "defconfig" en el que reporta pérdida de una dependencia, se resuelve instalando nuevamente el paquete y corriendo nuevamente el comando, recuerda, esto se hace facilmente con

 sudo apt-get install ''NOMBRE_DEL_PAQUETE'' 

Cualquier duda: Buscar "instalar NOMBRE_DEL_PAQUETE' en debian" en Google.

Volvemos a correr
 
 make defconfig 

Finalmente debemos tener este informe:
Checking 'working-make'... ok.
Checking 'case-sensitive-fs'... ok.
Checking 'getopt'... ok.
Checking 'fileutils'... ok.
Checking 'working-gcc'... ok.
Checking 'working-g++'... ok.
Checking 'ncurses'... ok.
Checking 'zlib'... ok.
Checking 'gawk'... ok.
Checking 'flex'... ok.
...
Y empieza a mostrar todas las caracteristicas de OpenWrt en bloque como:
* Wireless Drivers
*
kmod-hostap............................. Host AP support for Prism2/2.5/3 (PACKAGE_kmod-hostap) [N/m/y/?] (NEW) n
kmod-ieee80211................................... 802.11 Networking stack (PACKAGE_kmod-ieee80211) [N/m/y/?] (NEW) n
kmod-ieee80211-softmac......................... ieee80211 SoftMAC support (PACKAGE_kmod-ieee80211-softmac) [N/m/y/?] (NEW) n
kmod-net-airo....................................... Cisco Aironet driver (PACKAGE_kmod-net-airo) [N/m/y/?] (NEW) n
kmod-net-ipw2100.................................... Intel IPW2100 driver (PACKAGE_kmod-net-ipw2100) [N/m/y/?] (NEW) n
kmod-net-ipw2200.................................... Intel IPW2200 driver (PACKAGE_kmod-net-ipw2200) [N/m/y/?] (NEW) n
kmod-net-prism54................................ Intersil Prism54 support (PACKAGE_kmod-net-prism54) [N/m/y/?] (NEW) n
kmod-rt2570............... Driver for Ralink RT2570 usb wireless chipsets (PACKAGE_kmod-rt2570) [N/m/y/?] (NEW) n
*
En general muestra caracterisiticas como: Tablas IP, discos, Kernel boots, Network, PPP daemon, Libreria, IPv6, Dispositivos, Cryptographic API modules, Monitor de hardware, Otros modulos (bluetooth, crc, pcmia, switch, ...), modulos de sonido, USB, video, Wireless Drivers, idiomas, LUA, .... Muy interesante

Realizar enlaces simbolicos

Antes de ir a la configuración actual de la imagen que se desea compilar se requiere construir "symlink" (enlaces simbólicos) entre los paquetes y el ambiente local de desarrollo.
 make package/symlinks
Debe generar algo así:
++ mkdir -p /home/andresgom/8.09/staging_dir/toolchain-mipsel_gcc3.4.6
++ cd /home/andresgom/8.09/staging_dir/toolchain-mipsel_gcc3.4.6
++ mkdir -p bin lib include stamp
 make[1] package/symlinks
 make[2] prepare-tmpinfo
Generar los Symlinks toma un tiempo, pero cuando ha sido finalizado, el sistema a compilar esta ubicado y listo para la acción.

Menu configuración

La configuración de la imagen que se desea compilar, basada en la plataforma de destino disponible es invocada por el comando:
 make menuconfig
Esto generará una interfaz azul con todas las características de OpenWrt, así:




Este menú permite seleccionar las configuraciones y paquetes que queremos elegir para compilar nuestra propia imagen de OpenWRT.

- Target System.

 Los equipos que funcionan con sistemas embebidos hace uso de "Chipset" (http://es.wikipedia.org/wiki/Circuito_integrado_auxiliar) que logra integras las funciones de procesamiento y hacer trabajar los periféricos, en el caso de los router wifi, la interfaz inalámbrica.
De acuerdo al chipset del dispositivo se debe compilar una determinada imagen de OpenWRT, es por eso que en esta opcion se encuentran enunciados de Broadcom, Atheros, Intel, etc., reconocidos desarrolladores de Chipsets.

En mi caso siempre uso dispositivos con chipset Atheros.






###########################

SIMULACIÓN:Qué es QEMU?


De Wikipedia: QEMU es un emulador de procesadores basado en la traducción dinámica de binarios (conversión del código binario de la arquitectura fuente en código entendible por la arquitectura huésped). QEMU también tiene capacidades de virtualización dentro de un sistema operativo, ya sea Linux, Windows, o cualquiera de los sistemas operativos admitidos, (de hecho es la forma más común de uso). Esta máquina virtual puede ejecutarse en cualquier tipo de Microprocesador o arquitectura (x86, x86-64, PowerPC, MIPS, SPARC, etc.). Está licenciado en parte con la LGPL y la GPL de GNU.
Se usa QEMU para simular la imagen compilada (o descargada de la Web) de OpenWrt (kamikaze).
Para instalar QEMU simplemente usamos la consola y los comandos de Debian
sudo apt-get install qemu
Con esto se descarga el paquete y se instala automáticamente.
El Qemu como tal no tiene interfaz gráfica y solo basta con ir hasta la carpeta donde esta la imagen a Emular y escribir qemu ARCHIVO.image
Pero existe una aplicación adicional para una interfaz gráfica de qemu, se llama qemu launcher

Cargar la imagen de OpenWrt

Este ejercicio se puede realizar con la imagen personalizada y compilada según el anterior manual, o simplemente descargando una de las imagenes compiladas y listas para los dispositivos específico.
Se realizará el ejercicio con base a una imagen desargada de la web de OpenWrt.
Entrando a http://downloads.openwrt.org/ tendremos acceso a los repositorios.
En la carpeta kamikaze/ se encuentran las imagenes de diversas versiones de OpenWrt.
Descargaremos la última imagen en esta época: Carpeta http://downloads.openwrt.org/kamikaze/8.09.1/x86/ Imagen: openwrt-x86-jffs2-128k.image
Al bajar la imagen lo recomendable es guardarla en una carpeta diferente a la que contiene el código de OpennWrt, en este ejecicio se creará una carpeta llamada "Simula" y quedará /home/"usuario"/Simula/
Nota: LA imagen al bajarla pesa 6.3 Mbps... mas adelante será de utilidad este dato.
Ingresamos a la carpeta
cd Simula
Como esa imagnes es de un disco duro, usamos la herramienta fdisk para obtener más informaicón.
:~/Simula$ fdisk openwrt-x86-jffs2-128k.image
El programa fdisk suministra información sobre las particiones, con él es posible crear o eliminar particiones y unidades lógicas y definir la partición activa, si es que no lo está.
fdisk preguntará:
Debe establecer cilindros.
Puede efectuar esta operación desde el menú de funciones adicionales.

Orden (m para obtener ayuda): 
En este proceso solicitamos ver las particiones del disco (cuidado, no nuestro disco duro, sino la imagen de disco de OpenWrt openwrt-x86-jffs2-128k.image) digitando p.
p
Con lo cual genrera:
Disco openwrt-x86-jffs2-128k.image: 0 MB, 0 bytes
16 cabezas, 63 sectores/pista, 0 cilindros
Unidades = cilindros de 1008 * 512 = 516096 bytes
Identificador de disco: 0x00000000

                    Disposit. Inicio    Comienzo      Fin      Bloques  Id  Sistema
openwrt-x86-jffs2-128k.image1   *           1           9        4504+  83  Linux
openwrt-x86-jffs2-128k.image2              10         107       49360+  83  Linux

Orden (m para obtener ayuda): 
Aqui es importante anotar el tamaño de los cilindros, en este caso 1008 y el tamaño del disco, en este caso 107
E insertamos q para salir
Orden (m para obtener ayuda): q
Ahora multiplicamos 107*1008, si se quiere usar la terminal, se usa el comando bc
Orden (m para obtener ayuda): bc
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type "warranty'. 
y podemos hacer operaciones
107*1008
107856
Esta cifra representa el tamaño de la imagen de disco.
Se va a utilizar este último dato para poner en ceros desde el sector cero hasta el 107856 de la imagen openwrt-x86-jffs2-128k.image. Se utiliza
:~/Simula$ dd if=/dev/null of=openwrt-x86-jffs2-128k.image seek=107856
donde
dd: escribi r alfo en algun lado if: imput file null: desde cero of: output file
Lo cual genera el siguiente informe:
0+0 registros de entrada
0+0 registros de salida
0 bytes (0 B) copiados, 9,4774e-05 s, 0,0 kB/s
Ahora miramos las propiedades del archivo de la imagen de OpenWrt openwrt-x86-jffs2-128k.image
:~/Simula$ ls -lh openwrt-x86-jffs2-128k.image 
Nos insforma:
-rw-r--r-- 1 andresgom andresgom 53M 2009-09-14 22:45 openwrt-x86-jffs2-128k.image

Emulación de OpenWrt

NOTA: el archivo pesaba cerca de 53 Megas, cuando hace poco pesaba 6,5 Megas, esto se explica por la gran catidad de ceros que se le introdujeron en el paso anterior.
Finalmente EMULAMOS convocando a QEMU y la imagen trabajada

:~/Simula$ qemu openwrt-x86-jffs2-128k.image
Se iniciará una ventana con la máquina virtual, algo así:

Carga como un sistema operativo común, con su propia rutina de booteo y demás. Luego de un rato se llega a esta pantalla:

En este momento solamente es necesario presionar ENTER para obtener la interfaz principal de OpenWrt:

NOTA: Si en algún momento hace Click en esta pantalla perderá el control del Mouse (puntero) para recobrarlo solamente hay que presionar CTRL y ALT al mismo tiempo.
Para poder simular OpenWrt en cuanto a conexión con la tarjeta de red del PC y que se pueda, por ejemplo, conectar a internet u otras redes es necesario configurar la tarjeta de red y el OpenWrt.

No hay comentarios:

Publicar un comentario en la entrada