Intéressé par des cours d'informatique en ligne ?
Visitez mon nouveau site https://www.yesik.it !

OpenWrt est une distribution Linux légère à destination des cibles embarquées. Mais, à l'instar d'autres distributions plus lourdes comme Debian ou RedHat, OpenWrt inclut également un système de gestion de paquets, qui permet d'ajouter ou de supprimer des logiciels à volonté. Néanmoins, étant donné les ressources limitées de la plupart des cibles embarquées, et l'organisation de la mémoire flash retenue par OpenWrt , il est souvent plus économique en terme d'encombrement mémoire de flasher directement la cible avec un firmware OpenWrt contenant les paquets souhaités et juste ceux-la. C'est la procédure à suivre pour construire un tel firmware OpenWrt personnalisé à partir d'une machine sous Debian GNU/Linux que je vais décrire ici.

Télécharger buildroot

Pour commencer, nous allons télécharger OpenWrt. Ou pour être exact, buildroot, le système de build d'OpenWrt. En effet, contrairement à ce qui se passe habituellement, le projet que nous allons télécharger dans quelques instants ne contiendra pas les sources d'OpenWrt! En fait, il s'agit plutôt d'un ensemble de scripts, de fichiers et de makefile permettant de choisir les paquets, de télécharger les sources et les outils, d'appliquer les patchs nécessaires et enfin de compiler un firmware OpenWrt.

Toute cette infrastructure porte le nom de buildroot et est disponible dans un dépôt subversion (SVN). Il va donc falloir installer subversion sur votre machine s'il n'y est pas déjà:

sylvain@openwrt-dev:~$ su root -c 'apt-get install subversion'

Remarque:

Pour cet article, ma machine de développement est une machine Debian Squeeze neuve dotée d'une installation minimale. Vraisemblablement, vous aurez nettement moins de paquets que moi à installer puisque certains devraient déjà être présents. Par ailleurs, vous verrez aussi que je n'utilise pas sudo mais plutôt su. C'est simplement que sur cette installation minimale sudo n'est pas présent.

Une fois subversion disponible sur la machine de développement, il est possible de télécharger buildroot. La page https://dev.openwrt.org/wiki/GetSource recense les commandes à utiliser selon la version d'OpenWrt qui vous intéresse. Pour ma part, je voulais Backfire 10.03, ce qui correspond à la commande suivante:

sylvain@openwrt-dev:~/openwrt$ svn co svn://svn.openwrt.org/openwrt/branches/backfire
[...]
Checked out revision 28265.
sylvain@openwrt-dev:~/openwrt$ ls
backfire

Comme vous le voyez, le projet est téléchargé dans un dossier. Et c'est désormais dans ce dossier que nous travaillerons:

sylvain@openwrt-dev:~/openwrt$ cd backfire

Maintenant que nous disposons du système de build d'OpenWrt, nous pouvons passer à l'étape suivante: déterminer les paquets à inclure dans le firmware.

Configuration

Choisir les paquets

La toute première étape de configuration va donc consister à choisir les paquets à installer dans votre firmware. Le script ./scripts/feeds fournit avec le buildroot d'OpenWrt va nous y aider. Mais il requiert certains utilitaires qui ne sont peut-être pas encore installés sur votre machine. Commençons par corriger cela:

sylvain@openwrt-dev:~/openwrt/backfire$ su root -c 'apt-get install build-essential'

Une fois les outils installés, vous pouvez commencer par mettre à jour les différents feeds. Cela consiste essentiellement à télécharger les descriptions des paquets disponibles à partir de différentes sources sur Internet:

sylvain@openwrt-dev:~/openwrt/backfire$ ./scripts/feeds update -a

En explorant le dossier ./feeds/ vous pourrez identifier les paquets qui vous intéressent, et les installer avec ./scripts/feeds install. Par exemple, en supposant que vous souhaitiez ajouter à votre firmware le paquet tftp-hpa – qui se trouve dans le répertoire feeds/packages/net/tftp-hpa – pour faire de votre cible un serveur tftp:

sylvain@openwrt-dev:~/openwrt/backfire$ ./scripts/feeds install tftp-hpa
Installing package 'tftp-hpa'

Ici, ce n'est pas le cas, mais si des dépendances avaient été nécessaires, elles auraient été installées également.

Piège:

L'installation n'installe pas réellement les paquets choisis dans le firmware final. Il s'agit plutôt de les ajouter au système de build. Pour que les paquets ainsi installés fassent parti du firmware compilé, il faudra encore les cocher dans menuconfig à l'étape suivante...

Menuconfig

La configuration à proprement parler se fait avec menuconfig – un outil de configuration similaire à celui du noyau Linux qui vous est peut-être familier si vous avez déjà eu l'occasion de compiler votre propre kernel:

sylvain@openwrt-dev:~/openwrt/backfire$ make menuconfig
[...]
Build dependency: Please install ncurses. (Missing libncurses.so or ncurses.h)
Build dependency: Please install zlib. (Missing libz.so or zlib.h)
Build dependency: Please install GNU awk.
Build dependency: Please install flex.
Build dependency: Please install unzip.
Build dependency: Please install python.

Selon la configuration de votre machine de développement, cette première tentative peut fonctionner ou pas. Dans mon cas, vous le voyez, un certain nombre d'outils sont manquants. Le site d'OpenWrt recense dans un tableau les paquets correspondants. Pour ma part, j'ai donc du installer les paquets suivants avant de poursuivre:

root@openwrt-dev:~# apt-get install \
                            libncurses5-dev \
                            zlib1g-dev \
                            gawk \
                            flex \
                            unzip \
                            python
sylvain@openwrt-dev:~/openwrt/backfire$ make menuconfig
Menuconfig (OpenWrt).png

Menuconfig (OpenWrt) — L'utilitaire menuconfig permet de configurer les options à utiliser pour compiler OpenWrt.


Les options principales à configurer sont l'architecture (target system) et le profil (target profil) qui contient les pilotes spécifiques à une cible particulière. Si votre cible n'est pas incluse, il existe un profil générique (Default profile) incorporant tous les pilotes.

En explorant les menus Base system, Libraries, Network, et suivants vous pourrez sélectionner d'autres composants à inclure ou exclure du firmware. Si vous avez installé des paquets avec ./scripts/feeds install, vous devriez les retrouver (quelque-part) dans menuconfig. Il faudra penser à les cocher pour qu'ils soient réellement compilés et fassent parti de l'image finale.

Menuconfig (OpenWrt tftp-hpa).png
Dans l'exemple décrit plus haut, j'avais ajouté le paquet tftp-hpa. En cherchant dans Network --> File transfert, je vois que je peux cocher tftp-hda pour installer le client TFTP, et/ou tftpd-hda pour installer le serveur.



Une fois la configuration terminée, quittez menuconfig (en pressant esc-esc – et sans oublier de répondre yes à la question voulez-vous enregistrer?). La configuration sera sauvegardée dans le fichier .config du répertoire courant. Un message de confirmation indique que vous pouvez lancer la compilation à l'aide de la commande make:

*** End of OpenWrt configuration.
*** Execute 'make' to build the OpenWrt or try 'make help'.

Remarque:

Si vous voulez effectuer d'autres modifications à votre configuration, vous pouvez refaire un make menuconfig.

Récupérer la configuration standard

La configuration manuelle avec menuconfig peut se révéler fastidieuse et on se sent vite submergé par le nombre d'options possibles, d'autant plus que leur rôle n'est pas toujours évident à saisir. Heureusement, les développeurs d'OpenWrt mettent à disposition en téléchargement la configuration utilisée pour construire les images disponibles sur leur site.

Ces configurations standards peuvent se télécharger à une adresse de la forme http://downloads.openwrt.org/backfire/10.03.1-rc5/ar71xx/config. Cette adresse correspond à celle de la configuration de backfire/10.03.1-rc5 pour ar71xx. Vous trouverez facilement les configurations pour d'autres versions et/ou architectures en explorant le site http://downloads.openwrt.org.

Une fois choisie la configuration qui vous convient, il suffit de la télécharger et de la copier dans le fichier .config de votre dossier de développement:

root@openwrt-dev:~# wget http://downloads.openwrt.org/backfire/10.03.1-rc5/ar71xx/config
root@openwrt-dev:~# cp config .config

Vous pouvez immédiatement lancer le build avec cette configuration. Ou faire un make menuconfig pour ajuster à votre convenance certaines des options.

Compilation

Une fois la configuration terminée, vous pouvez lancer la compilation en tapant make. Si vous disposez d'un système multicœur ou multiprocesseur vous souhaiterez sans doute spécifier avec l'option -j le nombre de tâches à effectuer en parallèle:

sylvain@openwrt-dev:~/openwrt/backfire$ make -j 9

Remarque:

Si vous avez compris le principe de fonctionnement de buildroot, vous avez compris que c'est seulement maintenant que les sources d'OpenWrt et des outils vont être téléchargés. Par ailleurs, certaines étapes ne peuvent pas être parallélisées ce qui ne permet pas d'utiliser toute la puissance disponible sur les machines modernes.

Autrement dit, même avec une machine surpuissante, la compilation n'est pas aussi rapide qu'on pourrait l'espérer. Munissez-vous donc d'un peu de patience. Prévoyez également pas mal d'espace disques: lors de mes tests, le dossier openwrt/backfire occupait environ 300Mo lorsqu'il ne contenait que buildroot et atteignait plus de 3,5Go à la fin de la compilation!

Après quelques (longues) minutes, la compilation devrait se terminer sans erreur. Vous trouverez un certain nombre de fichiers dans le répertoire bin/architecture:

sylvain@openwrt-dev:~/openwrt/backfire$ ls -F bin/ar71xx/
md5sums
openwrt-ar71xx-rootfs.tar.gz
openwrt-ar71xx-root.jffs2-128k
openwrt-ar71xx-root.jffs2-64k
openwrt-ar71xx-root.squashfs
openwrt-ar71xx-root.squashfs-4k
openwrt-ar71xx-tl-wr1043nd-v1-squashfs-factory.bin
openwrt-ar71xx-tl-wr1043nd-v1-squashfs-sysupgrade.bin
openwrt-ar71xx-uImage-gzip.bin
openwrt-ar71xx-uImage-lzma.bin
openwrt-ar71xx-vmlinux.bin*
openwrt-ar71xx-vmlinux.elf*
openwrt-ar71xx-vmlinux.gz
openwrt-ar71xx-vmlinux.lzma
packages/

Le fichier qui m'intéresse ici est celui dont le nom contient le mot factory. Il s'agit du firmware complet prêt à être installé.

Installation sur la cible

L'installation de ce firmware peut se faire par toutes les méthodes habituelles pour OpenWrt: par port série, par tftp, par l'outil de mise à jour du fabriquant (dans le cas d'une cible neuve), etc.

Mais, si votre cible tourne déjà sous OpenWrt et que vous voulez installer un nouveau firmware, une solution plus simple est d'utiliser l'outil mtd. C'est la technique que je vais employer ici. L'installation se passe en deux temps:

  1. tout d'abord, nous allons télécharger l'image dans la RAM de la cible,
  2. puis nous allons utiliser mtd pour copier le firmware de la RAM vers la mémoire flash.

Pour le transfert, vous avez de nombreuses options à votre disposition selon les paquets déjà installés sur votre cible OpenWrt et sur votre machine de développement (http, ftp, tftp, ...). Ici, je vais faire très simple en utilisant scp qui permet de copier un fichier d'une machine à l'autre par SSH...

sylvain@openwrt-dev:~/openwrt/backfire$ scp bin/ar71xx/openwrt-ar71xx-tl-wr1043nd-v1-squashfs-factory.bin \
                 root@10.129.38.123:/tmp/

Dans cette commande 10.129.38.123 est évidemment l'adresse de ma cible. Par contre, un point important est de copier le fichier vers /tmp. En effet, sur une cible OpenWtr, un ramdisk est monté sur /tmp. C'est à dire que le fichier sera copié en RAM, et non pas dans la mémoire flash (que nous allons écraser lors de l'installation du firmware).

Je vous conseille aussi de copier vers votre cible le fichier md5sums qui permettra de vérifier l'intégrité du téléchargement:

sylvain@openwrt-dev:~/openwrt/backfire$ scp bin/ar71xx/md5sums \
                 root@10.129.38.123:/tmp/

Le reste des manipulations se fera sur la cible. Ouvrez une session ssh dessus, et, si vous avez téléchargé les sommes de contrôle md5, commencez par vérifier l'intégrité de l'image téléchargée:

sylvain@openwrt-dev:~/openwrt/backfire$ ssh root@10.129.38.123
  _______                     ________        __
 |       |.-----.-----.-----.|  |  |  |.----.|  |_
 |   -   ||  _  |  -__|     ||  |  |  ||   _||   _|
 |_______||   __|_____|__|__||________||__|  |____|
          |__| W I R E L E S S   F R E E D O M

root@MyTarget:~# cd /tmp
root@MyTarget:/tmp# grep factory md5sums | md5sum -c
openwrt-ar71xx-tl-wr1043nd-v1-squashfs-factory.bin: OK

Si le fichier est OK, il est temps de passer à l'étape-qui-fait-peur: flasher le firmware. Une dernière vérification s'impose, histoire de se convaincre que tout est vraiment en ordre. Commençons par vérifier le plan mémoire actuel de votre cible:

root@MyTarget:/tmp# cat /proc/mtd 
dev:    size   erasesize  name
mtd0: 00020000 00010000 "u-boot"
mtd1: 00140000 00010000 "kernel"
mtd2: 00690000 00010000 "rootfs"
mtd3: 00470000 00010000 "rootfs_data"
mtd4: 00010000 00010000 "art"
mtd5: 007d0000 00010000 "firmware"

La ligne qui m'intéresse est celle dont le nom est firmware. C'est là que va devoir être copié votre nouveau firmware. Une vérification de la taille me permet de m'assurer que l'image va bien tenir dans cet espace:

root@MyTarget:/tmp# ls -l openwrt-ar71xx-tl-wr1043nd-v1-squashfs-factory.bin
-rw-r--r--    1 root     root      8126464 Sep 21 16:12 openwrt-ar71xx-tl-wr1043nd-v1-squashfs-factory.bin

Là, un peu d'arithmétique s'impose: /proc/mtd donne la taille en hexadécimal, alors que ls -l la donne en décimal. Jetez-vous sur n'importe quel convertisseur pour vérifier que 812646410≤007d000016

Mais assez tergiversé. Il est temps de copier le firmware:

root@MyTarget:/tmp# mtd -r write openwrt-ar71xx-tl-wr1043nd-v1-squashfs-factory.bin firmware
Unlocking firmware ...
Writing from openwrt-ar71xx-tl-wr1043nd-v1-squashfs-factory.bin to firmware ...     
Rebooting ...

Cette commande indique d'écraser (write) le contenu de la zone mémoire appelée firmware avec l'image indiquée. L'option -r force le redémarrage de la cible après l'écriture de la mémoire flash. Il va de soi qu'interrompre d'une manière ou d'une autre la copie du firmware avant la fin serait assez catastrophique pour votre cible, et nécessiterait une réinstallation au mieux à partir de la console série du bootloader, au pire en utilisant un programmateur externe pour reflasher l'EEPROM! Si vous voulez vraiment être extrêmement prudent, vous pourrez alimenter votre cible par un onduleur pour le flashage du firmware afin de vous prémunir contre les coupures de courant...

Si vous n'avez pas commis d'erreur majeure dans la configuration de votre firmware OpenWrt personnalisé, votre cible devrait rebooter sans problème, et être accessible quelques secondes après. Par contre, comme nous avons ré-installé un nouveau firmware, vous avez perdu toute la configuration locale de votre cible. Celle-ci redémarre avec les valeurs par défaut (notamment adresse en 192.168.1.1 sur le port LAN, DHCP sur le port WAN).

Vérification

D'accord, nous avons installé un nouveau firmware. Mais qu'est-ce qui prouve qu'il contient bien les paquets que nous souhaitions? Une solution pour se convaincre que c'est bien un firmware avec les options que nous avons configurées qui est installé est de vérifier la présence des paquets spécifiques demandés. Ici, je vais vérifier que le paquet tftpd-hpa est bien présent:

root@OpenWrt:~# opkg list-installed | grep tftp
tftpd-hpa - 0.48-2

Effectivement: il y est! On peut aussi vérifier que le service est démarré:

root@OpenWrt:~# ps | grep tftp
  960 root      1020 S    tftpd-hpa -l -s /var/tftpd-hpa 

Et finalement, si tout cela n'est pas assez convainquant, il reste possible de faire un test fonctionnel du serveur tftp en plaçant un fichier sur la cible, et en le téléchargeant à partir d'un client sur le réseau:

# Sur la cible OpenWrt
root@OpenWrt:~# echo 'It works!' > /var/tftpd-hpa/test
# Sur le client tftp
client-tftp$ tftp 192.168.1.1
tftp> get test /dev/stdout
It works!
Received 10 bytes in 0.0 seconds

Ressources