lundi 6 octobre 2008

Fonera 2 : Personnaliser, compiler, regénérer OpenWRT

OpenWRTNous allons voir dans cet article l'environnement de développement de OpenWRT (kamikaze). Étant un système embarqué, OpenWRT est souvent destiné à  fonctionner sur des architectures différentes de votre machine de bureau. Pour cela il faut mettre en place un environnement de cross-compilation permettant de compiler des binaires pour une architecture différente. Pour la Fonera, par exemple, il me faut générer des binaires MIPS à  partir d'une machine x86.

L'équipe d'OpenWRT propose plusieurs outils qui permettent de réaliser cette tà¢che, réputée compliquée, avec une facilité indécente. Nous allons passer en revue ces différents outils de manière à  trouver celui en adéquation avec chaque besoin. Tout au long nous prendrons en exemple la Fonera.

Selon ce que vous voulez faire, vous n'aurez pas besoin d'installer l'environnement complet de développement. Nous pouvons distinguer trois niveaux en fonction de la tà¢che :

  • ImageBuilder pour générer un firmware personnalisé ;
  • le SDK pour compiler de nouveaux paquets ;
  • BuildRoot qui est l'environnement complet.

Les deux premiers sont en fait des version allégées et adaptées du 3ème.

ImageBuilder

Avec ImageBuilder, nous allons pouvoir adapter la distribution OpenWRT à  nos besoins (le filesystem pour être précis). Typiquement pour ajouter des paquets non présents dans la version de base, en retirer, préparer une configuration spécifique ... Cet outil vient donc avec des versions binaires de tous les paquets standards.

Pour la Fonera et kamikaze 7.09, vous le téléchargez ici. Prenez le fichier ImageBuilder correspondant à  votre architecture de développement (i686 ou x86_64).

Pour ajouter un paquet :

$ cp /tmp/hello_1-1_mips.ipk packages/
$ make image PACKAGES="hello"

Pour ajouter des fichiers, construisez votre arborescence dans un répertoire (par exemple /tmp/files/etc/monfichier.conf)

$ make image FILES="/tmp/files"

et monfichier.conf sera ajouté au répertoire etc de votre image.

$ make help

vous explique tout cela.

Note: Il semble que les Profiles ne fonctionnent pas avec ImageBuilder.

SDK

GCC Le SDK va nous permettre de compiler de nouveaux paquets pour OpenWRT. Il inclu donc les binaires de compilation croisées (mips-linux-uclibc-gcc par exemple) qui vont vous permettre de générer des exécutables MIPS à  partir d'une machine PC. Nous pouvons donc l'utiliser pour générer des paquets existants avec une configuration différente voir créer carément de nouveaux paquets.

Vous le téléchargez au même endroit mais cette fois il s'agit du fichier SDK. De même décompressez le dans un répertoire de travail.

Deux erreurs ?

Avant d'aller plus loin, chez moi j'ai rencontré deux erreurs lors du make avec le SDK Kamikaze 7.09 pour Atheros.

$ make
/bin/sh: Syntax error: "&" unexpected
make: *** [world] Erreur 2

Bizarement celle-la se résoud en augmentant le niveau de verbosité :

$ make V=99

à  chaque fois que vous utilisez make

Deuxième erreur :

make: option requires an argument -- C
Usage: make [options] [target] ...
Options:
  -b, -m                      Ignored for compatibility.
  -B, --always-make           Unconditionally make all targets.
  -C DIRECTORY, --directory=DIRECTORY
                             Change to DIRECTORY before doing anything.
...

Il suffit de remplacer le ; par un . à  la ligne 79 du Makefile :

                      xargs -n1 $(MAKE) compile -C. \

Ce qui est étrange, c'est que je n'ai pas ces problèmes avec le BuildRoot.

Ajouter un paquet existant

Pour générer un paquet que vous n'avez pas, il vous suffit de copier le répertoire source dans package et de taper make à  la racine du SDK.

Avant de vous lancer dans la création d'un nouveau paquet, je vous invite à  aller voir si quelqu'un ne s'en ai pas déjà  chargé. Dans le cas contraire, suivez le guide ...

Hello world!

Pour commencer essayons de générer le fameux Hello world!. Positionnez vous dans le répertoire du SDK puis :

$ cd tmp
$ cat > hello.c
#include <stdio.h>
int main (int argc, char * argv)
{
   printf ("Hello world!\n");
   return 0;
}
^D

Compilons le et exécutons le sur la Fonera[1] :

$ ../staging_dir_mips/bin/mips-linux-uclibc-gcc hello.c -o hello -I../staging_dir_mips/include
$ scp hello root@fonera:/tmp
$ ssh root@fonera /tmp/hello
Hello world!

Construire un paquet

Paquet Bon, c'est bien joli, mais ça manque d'automatisation. Nous allons en faire un paquet. Créez les répertoires hello/src dans le dossier package du SDK et copiez y hello.c.

Voici donc les sources de notre paquet. Maintenant il faut créer un fichier de contrôle pour que le SDK sache comment générer et installer nos fichiers. Créons donc un fichier Makefile situé dans package/hello. Il doit contenir :

include $(TOPDIR)/rules.mk

PKG_NAME:=hello
PKG_RELEASE:=1
PKG_VERSION:=1

PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)

include $(INCLUDE_DIR)/package.mk

define Package/hello
	SECTION:=utils
	CATEGORY:=Utilities
	TITLE:=hello
	DESCRIPTION:=The Hello World
endef

define Build/Compile
	mkdir -p $(PKG_BUILD_DIR)
	$(CP) ./src/* $(PKG_BUILD_DIR)/
	$(TARGET_CC) $(PKG_BUILD_DIR)/hello.c -o $(PKG_BUILD_DIR)/hello
	## $(MAKE) CC=$(TARGET_CC) -C $(PKG_BUILD_DIR)
endef

define Package/hello/install
	$(INSTALL_DIR) $(1)/usr/bin
	$(INSTALL_BIN) $(PKG_BUILD_DIR)/hello $(1)/usr/bin
endef

$(eval $(call BuildPackage,hello))

Voyons rapidement la syntaxe : au début et dans la section Package/hello on renseigne des variables décrivant le paquet (nom, versions, description ...).

Dans la section Build/Compile, la manière de compiler les sources. Copie des fichiers dans le répertoire de compilation et appel du compilateur croisé (TARGET_CC). Notez aussi la ligne en commentaire qui servirait dans le cas ou on aurait un Makefile pour les sources.

Enfin viens la section Package/hello/install qui indique quels fichiers installer ou. Création de /usr/bin et copie de hello dedans.

Vous pouvez trouver une description plus détaillée du format de fichier dans la doc BuildRoot. Enfin, il faut signaler que le SDK est capable de télécharger automatiquement des sources[2] simplifiant encore le fichier de contrôle.

Je vous invite aussi à  aller voir les sources pour pleins d'exemples.

Une fois ceci fait, positionnez vous à  la racine du SDK et tapez simplement :

$ make

le SDK va détecter les nouveaux packages et lancer le processus de génération de ceux-ci. Une fois terminé, vous trouverez les fichiers .ipk dans bin/packages. Il ne vous reste plus qu'a le copier sur la Fonera pour l'installer.

$ scp bin/packages/hello_1-1_mips.ipk root@fonera:/tmp
$ ssh root@fonera
...
root@OpenWrt:~# ipkg install hello_1-1_mips.ipk
root@OpenWrt:~# hello
Hello world!

\o/ Youhou !

Vous trouverez ici les sources et binaires

Buildroot

TuXAlors la, c'est du lourd. L'environnement complet de développement, vous allez pouvoir tout recompiler et hacker le noyau comme des petits fous. :) Comme il s'agit d'un sur-ensemble des deux outils précédents, vous pouvez bien sur utiliser BuildRoot pour simplement compiler un package ou générer un filesystem perso. A noter qu'une très bonne documentation est disponible.

Génération

Pour récupérer le BuildRoot Kamikaze 7.09, faites simplement :

$ svn co https://svn.openwrt.org/openwrt/tags/kamikaze_7.09/

ou alors :

$ wget http://downloads.openwrt.org/kamikaze/7.09/kamikaze_7.09.tar.bz2 && tar xvjf kamikaze_7.09.tar.bz2

Les gentils dev d'OpenWRT nous ont concocté un joli menu pour configurer tout ceci :

$ make menuconfig

Vous pouvez alors choisir la cible, quelques options de configuration, les images à  générer et les paquets à  inclure dans votre image. Vous pouvez aussi reconstruire ImageBuilder et le SDK. Si vous voulez changer des options du noyau[3], utilisez :

$ make kernel_menuconfig

Pour la Fonera, choisissez Atheros [2.6] comme cible.

Enfin, il est temps de compiler/générer tout cela. tapez simplement :

$ make

et allez raconter 12 histoires à  vos enfants. Chez moi (Athlon XP 1600+) ça a mis 1h30. Toutes les sources nécessaires sont téléchargées, patchées, le compilateur croisé est construit ainsi que le noyau et le filesystem. A la fin, vous trouvez ce qui vous intéresse dans le répertoire bin.

$ ls bin/
openwrt-atheros-2.6-root.jffs2-128k  openwrt-atheros-2.6-vmlinux.elf
openwrt-atheros-2.6-root.jffs2-256k  openwrt-atheros-2.6-vmlinux.gz
openwrt-atheros-2.6-root.jffs2-64k   openwrt-atheros-2.6-vmlinux.lzma

Lors des prochains make seules les parties nécessaires seront reconstruites. En particulier le compilateur ne sera pas recompilé à  chaque fois. :)

A noter quelques autres répertoires intéressants :

  • build_mips : contient tout ce qui a été compilé et généré. En particulier build_mips/root le système de fichiers ;
  • staging_dir_mips : le cross-compiler ;
  • package : les sources des paquets (fichiers de contrôle, patchs ...) ;
  • dl : les sources téléchargées lors de la construction.

Packages

Pour ajouter votre propre package, procédez comme avec le SDK. Puis lors du menuconfig, sélectionnez le simplement.

menuconfig

Fichiers

Si vous voulez ajouter des fichiers à  cette image, créez un répertoire files. Par exemple pour changer la configuration réseau par défaut :

mkdir -p files/etc/config
cat > files/etc/config
## Attention, il manque lo !!
config interface lan
       option ifname   eth0
       option proto    dhcp
       option hostname fonera

Lors du prochain make, BuildRoot remplacera la configuration réseau de package/base_files par la votre.

Émulation MIPS

Qemu logo Autant vous prévenir tout de suite, il ne semble pas possible d'émuler votre Fonera, même si quelques travaux existent.

Par contre, il est possible de lancer un programme MIPS sur votre PC :

$ cd /data/OpenWrt/kamikaze_7.09/build_mips/
$ qemu-mips -L /data/OpenWrt/kamikaze_7.09/build_mips/root root/bin/busybox

avec le SDK et notre programme hello ci-dessus :

$ qemu-mips -L /data/OpenWrt/OpenWrt-SDK-atheros-2.6-for-Linux-i686/staging_dir_mips/ hello

Cela peut vous permettre de tester quelques commandes. Mais à  priori pour le kernel, il vous faudra flasher.

Visiblement il existe pleins d'émulateurs MIPS mais je n'ai pas eu le courage d'en tester d'autres.

Voila, nous sommes maintenant capables de

  • ajouter des fichiers et des paquets dans une image sans rien recompiler ;
  • compiler des programmes, des paquets et en faire de nouveaux ;
  • regénerer un OpenWrt complet noyau y compris.

Nous voila prêts pour de nouvelles aventures au prochain épisode, porter open2300 sur la Fonera et lui donner accès au port série.

Liens

La doc de WhiteRussian, plutôt obsolète.

La doc de Kamikaze :

  • Moteur de recherche de paquets ipkg

Notes

[1] on pourra aussi émuler, mais on verra ça plus tard

[2] par exemple sur sourceforge

[3] et voir de jolis oops :)


Commentaires du post original

mercredi 1 octobre 2008

Fonera et Station météo 1 - Port serie et OpenWRT

Je me suis acheté récemment pour une somme modique une Fonera. Mais je n'ai pas l'intention de faire parti du réseau FON. L'utilité que je vois à  celle-ci est de disposer d'un système embarqué supportant linux et disposant d'un port série, réseau et wifi.

Le projet

Fonera
En effet ce genre de petite carte à  faible consommation revient généralement assez cher ! Vous trouverez quelques exemples dans mes bookmarks mais il est difficile de trouver quelque chose à  moins de 60EUR port exclu. La Fonera se présente alors comme une alternative crédible même si ses possibilités sont assez limitées.
Mon but est, à  terme, de l'utiliser comme mini-serveur web pour accéder aux données de ma station météo. Elle devrait pouvoir remplacer avantageusement un PC complet pour ce simple service. Ses capacités semblent tout-à -fait suffisantes :
  • support de Linux et en particulier de l'excellent OpenWRT ;
  • port série pour dialoguer avec la station ;
  • interface réseau filaire et Wifi ;
  • 4 GPIO disponibles sur lesquels on peut connecter une SD card pour la capacité de stockage.
Bref tout ce qui est nécessaire pour seulement 15EUR dans mon cas et pour une consommation électrique sans commune mesure : 3.2W en pic au boot et 2.6W en idle[1].
WS2300Les étapes nécessaires à  ce projet sont donc :
  1. réalisation d'un connecteur pour le port série ;
  2. flashage de la Fonera avec OpenWRT ;
  3. configuration/modification pour rendre le port série disponible pour la station météo ;
  4. compilation de open2300 sur la fonera ;
  5. réalisation du support de stockage de masse (SDcard) ;
  6. configuration du serveur web.
Rien de révolutionnaire dans ce projet, toutes les étapes sont déjà  parfaitement documentées un peu partout sur le web.

Connecteur série

Première étape, la réalisation d'un connecteur pour le port série.
Je ne vais pas détailler le montage, tout est déjà  très bien expliqué sur l'excellent blog de Denis Bodor[2] (y'a même un typon). Autant vous prévenir tout de suite, c'est une référence en ce qui concerne le hack de Fonera. D'ailleurs regardez le dernier article du GLMF de ce mois :)
D'abord, un petit test sur plaque d'essai. J'ai utilisé des transistors 2N2218 plutôt que les 2N2222 car c'est ce que mon fournisseur[3] avait en stock :)
essai essai
Attention, sur le Wiki OpenWRT, RXD et TXD du port fonera correspondent au coté PC ! Chez Denis par contre c'est OK.
Ensuite, la mise en place sur plaque pastillée. Les composants sont assez serrés car je veux loger tout ça dans une petite boite. Comme l'ensemble du montage sera à  coté de la station météo dans le salon, il faut que ça reste relativement propre.
placement recto verso
La nappe coté fonera est découpée dans une nappe IDE, celle coté PC vient d'une poubelle. J'ai du acheter la boite chez Selectronic pour un projet oublié depuis :)
Et voila, la Fonera est branchée et dialogue avec le PC !
fini

Quelques trucs avant de flasher

On peut commencer par se connecter en ssh[4] via le réseau filaire.
# autorise les connections tcp
iptables        -A input_rule      -i eth0 -p tcp  -j ACCEPT
iptables -t nat -A prerouting_rule -i eth0 -p tcp  -j ACCEPT
# lance dropbear
/etc/init.d/dropbear
On attend un peu que les clefs soient générées, puis :
ssh root@192.168.0.149  ## bien sur remplacez par l'adresse de votre fonera !
root@192.168.0.149's password: admin
Voila, c'est plus convivial que le lien série.
Ensuite, on sauvegarde les partitions actuelles. La méthode proposée sur le wiki OpenWRT ne fonctionne pas chez moi, j'en ai trouvé une autre ici
cd /dev/mtd
for f in *ro; do echo -n "processing $f."; cat $f | gzip >/tmp/$f.gz; echo " Done."; done
scp /tmp/*.gz jjl@penfret:/home/jjl/
Conservez aussi le contenu du fichier /proc/mtd

Flasher avec OpenWRT

logo Je me propose d'utiliser ici la méthode RedBoot via port série. Une autre très courrue est via telnet.
On installe un serveur tftpd, par exemple sur une ubuntu :
sudo aptitude install tftpd
Chez moi, il est lancé à  la demande par inetd. Les fichiers à  servir sont situés dans /srv/tftp[5], répertoire à  créer. On récupère alors le noyau et le filesystem pour atheros (le processeur de la fonera)
cd /srv/tftp
wget http://downloads.openwrt.org/kamikaze/7.09/atheros-2.6/openwrt-atheros-2.6-vmlinux.lzma
wget http://downloads.openwrt.org/kamikaze/7.09/atheros-2.6/openwrt-atheros-2.6-root.squashfs
La, je vous conseille de suivre cette méthode. Ne recopiez pas directement les lignes suivantes, allez lire l'article pour avoir toutes les explications !
RedBoot> ip_address -h 192.168.0.105 -l 192.168.0.149/24
RedBoot> fis init
RedBoot> lo -r -b %{FREEMEMLO} openwrt-atheros-2.6-vmlinux.lzma
RedBoot> fi cr -e 0x80041000 -r 0x80041000 vmlinux.bin.l7
RedBoot> fis free
La vous faites la différence entre les deux valeurs hexa données.
RedBoot> lo -r -b %{FREEMEMLO} openwrt-atheros-2.6-root.squashfs
RedBoot> fi cr -l 0x6F0000 rootfs ## Remplacez la valeur par la différence précédement calculée
RedBoot> fis load -l vmlinux.bin.l7
RedBoot> exec
Ne reste plus qu'a adapter la configuration comme le dhcp, le password root à  définir ...
Voila pour aujourd'hui. Prochaine étape, construire un environnement de cross-compilation pour régénérer un openwrt et open2300

Liens utiles

Je ne vais pas vous lister ici tous les liens sur la fonera ou OpenWrt, mais juste ceux qui me paraissent le plus pertinents dans mon cas.
Tout d'abord ceux qui ont eu la même idée que moi :
  • EquinoxeFR mais j'ai l'impression qu'il a changé de politique après l'étape 1
  • Puis ici openwrt/open2300 mais sur un routeur Asus
  • open2300 pour WhiteRussian
Puis sur la Fonera

Notes

[1] sans le wifi
[2] Quoi ? Il n'est pas encore dans vos flux RSS ! Mais ajoutez-le immédiatement !
[3] qu'il soit béni jusqu'à  la 7ème génération
[4] en one-shot, au prochain démarrage, il faudra recommencer
[5] voir /etc/inetd.conf


Commentaires du post original