Aquí se muestra una forma de construir una imagen de firmware para grabarla en un dispositivo enrutador o en uno embebido, todo esto usando el sistema de construcción "[Build root](https://wiki.openwrt.org/about/toolchain)" de sistemas operativos libres como openwrt, lede o librecmc.

En otras palabras, construir/compilar **el sistema operativo manualmente** y ponerlo en un enrutador compatible.

Algunas ventajas de usar "Build root" son:

* La generación de la imagen es altamente personalizable y tendrá los programas que escojamos en el proceso de construcción.
* Construir el conjunto de paquetes e incluirlos en la imagen resultante o en paquetes por separado.
* Constuir y poder usar la cadena de herramientas (en inglés *toolchain*) para hacer compilación cruzada.
* Obtener el [SDK](https://es.wikipedia.org/wiki/Kit_de_desarrollo_de_software) para hacer compilación cruzada desde otra computadora.
* Obtener el [Image generator](http://wiki.openwrt.org/doc/howto/obtain.firmware.generate) para poder cocinar imágenes de firmware más rápidamente desde otra computadora.
* Constuir los programas y mantenerlos en paquetes instalables o incluirlos por defecto en la imagen generada.
* Generar un repositorio *descargable* de paquetes e imágenes de firmware personalizadas generadas como este: [https://librecmc.rmgss.net](https://librecmc.rmgss.net/)
* Hacer modificaciones/mejoras al sistema operativo resultante.

Este alto nivel de flexibilidad es justo lo que se necesita para proyectos de *redes libres* o para personas que necesitan hacer modificaciones a nivel de sistema operativo en sistemas embebidos.

## Construyendo firmware para aparatos enrutadores usando buildroot ##

Build root, es una colección de Makefiles y parches que permiten fácilmente generar una cadena de herramientas y el sistema de archivos raíz para sistemas embebidos, usando una biblioteca C estándar y descargando el kernel linux. [^1]

Este sistema de construcción tiene una interfaz cómoda que permite seleccionar los programas que necesitemos y los dispositivos objetivos. Los [Makefiles](https://es.wikipedia.org/wiki/Make) son archivos con recetas de construcción de software, y el sistema de construcción Build root los utiliza para constuir los programas que seleccionemos.

-- Para el resto de este tutorial se utilizará el **sistema de construcción de [librecmc](https://gogs.librecmc.org/libreCMC/libreCMC/wiki/How-To-Build-libreCMC)**, librecmc es una distribución GNU/Linux para sistemas embebidos que contiene solamente software libre.

### Prerequisitos ###

Hardware:

* De 8 a 10 GB de espacio en disco duro.
* 4 GB de RAM , aunque yo lo he probado con 2 GB de RAM pero ha tardado mucho.

Software:

* Sistema operativo GNU/Linux
* GNU GCC / GCC-C++
* build-essential
* flex, gawk, wget, unzip
* ncurses-dev (ncurses5-devel, etc..)
* libghc-zlib-dev, libssl-dev, patch, perl5, subversion, git-core

Internet:

Una *buena conexión a internet* por que la descarga puede tranquilamente superar los **2 GB**, en mi caso al no tener internet en casa he usado un Servidor con buena conexión.

[Aquí esta](https://gogs.librecmc.org/libreCMC/libreCMC/wiki/How-To-Build-libreCMC#what-do-i-need-to-get-started) la referencia oficial.

### 1. Instalar herramientas de software ###

Se instalan los paquetes build-essential, gcc, git-core, etc como se indican en los prerequisitos.

Luego queda descargar el sistema de construcción en si mismo como se indica en el manual de librecmc:

    :::bash
	git clone https://gogs.librecmc.org/libreCMC/libreCMC.git

Esto descargará la colección de Makefiles y parches necesarias para el proceso de construcción, la estructura de directorios descargada se divide en carpetas:

* **tools**: Contiene las instrucciones para descargar las herramientas de construcción para la imagen.
* **toolchain**: Contiene las instrucciones para descargar las cabeceras del kernel, la biblioteca C, binutils, el compilador y el depurador.
* **target**: Instrucciones de construción para la imagen de fimrware y para el kernel.
* **package**: Los makefiles y parches para todos los paquetes principales, estos Makefiles tienen su propia sintaxis diferente a la herramienta make.
* **scripts**: Scripts perl que se encargan del manejo de paquetes openwrt.
* **dl**: Directorio donde se descargan los tarballs (archivos .tar) con código fuente.
* **build_dir**: Donde todas las herramientas user-space serán "cross-compiladas".
* **bin**: Directorio donde se guardan las imágenes de firmware generedas y también los paquetes .ipk

Referencia utilizada: [http://www.ccs.neu.edu/home/noubir/Courses/CS6710/S12/material/OpenWrt_Dev_Tutorial.pdf](http://www.ccs.neu.edu/home/noubir/Courses/CS6710/S12/material/OpenWrt_Dev_Tutorial.pdf)

### 2. Actualizar las lista de paquetes ###

Entramos al directorio donde hemos clonado el código de buildroot, `cd libreCMC` y ejecutamos:

    :::bash
    ./scripts/feeds update -a
	./scripts/feeds install -a

Esto actualizará la lista de todos los paquetes y hará que sean disponibles para seleccionar en el menú de construcción.

### 3. Configurar la compilación ###

Utilizamos

    :::bash
    make menuconfig
	
Esto desplegará un menú con interfaz en modo texto cómodo para configurar la construcción.

![make menuconfig](../static/imgs/posts/make-menuconfig-librecmc.jpg)

Navegar por el menú se hace con las flechas del teclado, presionando `enter` para ingresar a una sección, `esc` para salir al anterior, `espacio` para seleccionar un programa para que se incluya en la imagen generada, `m` para modularizar o marcar un programa y que se genere un paquete `.ipk` en lugar de incluirlo en la imagen generda por defecto.

#### Arquitectura y dispositivo objetivo ####

El menú desplegado tiene varias secciones y debemos empezar indicando la **arquitectura objetivo**, esta debe ser la arquitectura del microprocesador del router o dispositivo embebido para el que queremos crear una imagen de firmware.

Para este ejemplo construiremos la imagen para el enrutador TP-Link **TL-MR3020**, ingresamos al menu "Target System" y marcamos Atheros AR7xxx/AR9xxx que corresponde a la arquitectura para este enrutador.

Luego hay que especificar el objetivo específico en este caso en el menu **Target Profile**, seleccionaremos TP-LINK TL-MR3020.

#### Image Builder y SDK ####

Antes de continuar para seleccionar los programas que contendrá la imagen vamos a seleccionar las opciones:

* **Build the librecmc Image Builder**: generará el Image Builder para poder descargarlo y generar imágenes desde otra computadora y más rapidamente.
* **Inlcude package repositories**: Para que el Image Builder generado use a repositorios externos para paquetes .ipk.
* **Build the librecmc SDK**: Construirá el SDK para poder descargarlo y usarlo en otra computadora, el SDK es útil para compilar programas para el enrutador objetivo.
* **Package the librecmc-based toolchain**: Empaquetar el toolchain (cadena de herramientas).

Este paso es opcional y la imagen se generaría de igual forma incluso si no lo seleccionamos.

#### Seleccionar los programas ####

Hay una gran variedad de programas que podemos incluir, por defecto están seleccionados programas básicos para utlizar el dispositvo y los estrictamente necesarios como libc y algunos controladores no pueden excluirse de la selección ya que el menú no da esa opción.

Los programas están bien clasificados por secciones y debemos ingresar a cada una de ellas para seleccionarlos, por ejemplo en *Base System* están marcados libc, busybox, uci, firewall, etc. Se puede prescindir de algunos de ellos por ejemplo no incluir el firewall desmarcándolo.

La selección de programas es enteramente nuestra responsabilidad y podemos experimentar con muchas opciones, por ejemplo no incluir una interfaz de configuración luci, no incluir controladores para wifi, no incluir un servidor dhcp, incluir módulos para controlar dispositovs usb, manejar los leds del aparato, incluir utilidades para monitorizar tráfico de red, estadísticas de conexión como iperf3, etc. Las combinaciones serán a nuestra elección y tenemos **toda la libertad de probar** bajo nuestro propio riesgo.

Lo que se debe tener en cuenta es que **no todos** los paquetes pueden ser incluidos en la imagen del firmware generada esto por limitaciones de espacio del mismo dispositivo. En el caso del TL-MR3020 este sólo cuenta con 4MB de memoria FLASH, y no se puede hacer caber todos esos programas en tan pequeño espacio de almacenamiento.

Por eso existe la opción de modularizar los programas, esto es presionando `M` para que estos programas se empaquten como `.ipk` y luego se puedan instalar manualmente con `opkg install nombre_del_paquete` en el dipositivo una vez se haya transferido la imagen y si tiene espacio disponible.

Una vez termines de seleccionar los programas presiona `esc` hasta salir y aparecerá un mensaje que pregunta si va a guardar las configuraciones y tenemos que indicarle que SI lo haga. Estas configuraciones se guardarán en un archivo con nombre `.config` en el mismo directorio y es buena idea hacerle copias para recuperar configuraciones.

##### Sobre la distribución de la memoria FLASH #####

Para aprovechar al máximo estos 4MB de memoria donde se debe almacenar el sistema operativo base y programas, openwrt y otros como librecmc y lede utlizan un layout especial en la memoria [^2].

Durante el arranque del sistema cuando instalemos la imagen generada, se crea un sistema de archivos de sólo lectura [squashfs](https://wiki.openwrt.org/doc/techref/filesystems#squashfs) para comprimir el sistema base y un sistema de archivos JFFS2 de lectura/escritura para datos adicionales. Ambos se combinan y montan en un punto de montaje /overlay, para el usuario del sistema se ve como un sistema de archivos único y usable. [^3]

SquashFS es un sistema de archivos de sólo lectura y está pensado para su uso como sistema de archivos genérico de solo lectura y en dispositivos de bloques/sistemas de memoria limitados [^4], en SquashFS además se incluye un sistema de recuperación en caso de "mal configurar" el router, con esta utilidad se puede entrar a un modo de recuperación para arreglar el sistema. Además algunos programas y datos de SquashFS y JFFS2 se descomprimen en la memoria RAM para ser ejecutados desde alli. En el caso del TL-MR3020 se tiene 32 MB de RAM.

Puedes revisar [https://wiki.openwrt.org/doc/techref/flash.layout](https://wiki.openwrt.org/doc/techref/flash.layout) para ver la distrubición de la memoria FLASH con mayor detalle.

### 4. Comenzar el proceso de construcción ###

Ahora solo queda emepezar la construcción y se hace con:

    :::bash
	make

O para una visión mucho más completa de lo que pasa:

    :::bash
    make V=s

Este proceso puede tardar mucho y es un trabajo intensivo para el CPU que puede tomar muchas horas dependiendo la cantidad de programas seleccionados y dispositivos objetivos.

Si quieres dejar este trabajo como tarea en segundo plano y además necesitas cerrar la terminal actual, puedes utilizar:

    nohup make &
	
Que enviará el proceso de construcción en segundo plano y continuará incluso si cerramos la terminal actual, además puedes usar `ionice` para aumentar/reducir prioridad a la tarea o `cpulimit` para limitar el uso del CPU.

El proceso puede fallar y si así lo hace debes usar la opción `make V=s` para ver el detalle.

Cuando hagas make, se hará:

1. Construir - automake , autoconf, sed, cmake.
2. Construir los binutils - ld, as ,etc
3. Construir el toolchain - gcc, g++, etc
4. Construir los módulos del kernel linux.
5. Constuir los paquetes base y feed.
6. Constuir la imagen del kernel.
7. Generar la imagen del firmware.

Referencia: [https://wiki.openwrt.org/about/toolchain#openwrt_build_system_build_sequence](https://wiki.openwrt.org/about/toolchain#openwrt_build_system_build_sequence)

### 5. Grabando la imagen generada en el router ###

La imagen generada debería estar en la carpeta `bin/targets` del directorio raíz donde hemos descargado Build Root, más concretamente `targets/ar71xx/` por ser la arquitectura ar71xx.

Un ejemplo del resultado está en [https://librecmc.rmgss.net/](https://librecmc.rmgss.net/)

Ahora seleccionaremos la imagen con nombre **librecmc-ar71xx-generic-tl-mr3020-v1-squashfs-factory.bin**, cuando termina `-factory.bin` se trata de la imagen que podemos grabar en el enrutador TL-MR3020 para reemplazar el sistema operativo actual.

El proceso de grabación no esta contemplado en este tutorial pero puedes revisar los siguientes enlaces:

* [https://wiki.lapaz.laotrared.net/guias/instalar_openwrt#paso_0](https://wiki.lapaz.laotrared.net/guias/instalar_openwrt#paso_0)
* [http://lamurraydemas.blogspot.com/2014/03/actualizar-tp-link-tl-mr3020-con-openwrt.html](http://lamurraydemas.blogspot.com/2014/03/actualizar-tp-link-tl-mr3020-con-openwrt.html)
* [http://kurup87.blogspot.com/2014/09/installing-open-wrt-in-tp-link-mr3020.html](http://kurup87.blogspot.com/2014/09/installing-open-wrt-in-tp-link-mr3020.html)


----

### Adicionales ###

El proceso de construción no se limita a generar la imagen de firmware, tambíen tengamos en cuenta lo siguiente:

* **staging_dir/**: Contiene el compilador y el toolchain (la cadena de herramientas) para la arquitectura seleccionada, el toolchain está en este caso en `staging_dir/toolchain-mips_24kc_gcc-5.4.0_musl-1.1.16/bin/` y podemos usarlo para hacer compilación cruzada y crear/construir programas para que se ejecuten en el router.
* **bin/packages/**: Contiene los paquetes `.ipk` que hemos seleccionado para instalarlos manualmente.
* **bin/targets/**: Contiene el [Image Generator](https://wiki.openwrt.org/doc/howto/obtain.firmware.generate) o Image Builder para construir firmware desde otras computadoras con GNU/Linux, usando los paquetes y programas que acabamos de construir, también contiene el [SDK](https://wiki.openwrt.org/doc/howto/obtain.firmware.sdk) para usarlo en otras computadoras con GNU/Linux y construir/compilar programas para el dispositivo objetivo que hemos selccionado.
* **dl/**: Contiene los tarballs con el código fuente de los programas seleccionados.

Con Build root hemos generado una serie de herramientas para generar sistemas operativos a medida gracias a las herramientas libres que proveen proyectos como [openwrt](https://openwrt.org/), [lede](https://lede-project.org/) o [librecmc](https://librecmc.org).

Además tenemos la posiblidad de tener el control y conocimiento entero de todo el sofware que opera en el enrutador.

Espero este tutorial te haya servido, lo actualizaré con información adicional o haciendo correcciones.

[^1]: https://wiki.openwrt.org/about/toolchain
[^2]: https://wiki.openwrt.org/doc/techref/flash.layout
[^3]: https://wiki.openwrt.org/doc/techref/filesystems#boot_process
[^4]: http://squashfs.sourceforge.net/

