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