Construire son système personnel sur une carte Pandaboard (3)

Publié par cpb
Mai 20 2011

Pandaboard Ethernet et USB

Dans les articles précédents (1 et 2) nous avons réussi à installer un système minimal sur notre Pandaboard. Toutefois, nous n’avons pour le moment pas abordé le problème du réseau. Je vous propose cette semaine d’initialiser l’interface Ethernet et d’installer quelques services, par exemple pour se connecter à distance ou transférer des fichiers sur la carte.

Initialisation de l’interface Ethernet

L’interface Ethernet de la carte Pandaboard est assurée par un composant SMSC LAN 9514. Celui offre un hub USB 2.0 ainsi qu’une interface RJ45 10/100 MBits/sec. Le driver de ce composant est bien présent dans le fichier de configuration du kernel que nous avons utilisé dans le premier article.

Toutefois, l’inconvénient de ce périphérique est que l’interface Ethernet utilise un support USB, et met ainsi plusieurs secondes après le boot à être détectée et initialisée par le noyau avant d’être accessible par l’espace utilisateur. Nous devrons donc utiliser une boucle d’attente avant de configurer l’interface.

Je vous propose de modifier le script d’initialisation précédent /etc/init.d/rcS pour ajouter les lignes suivantes à la fin du fichier :

while true
do
    if ifconfig -a | grep '^eth0' > /dev/null
    then
        break;
    fi
    sleep 1
done

ifconfig eth0 192.168.3.152
ifconfig lo 127.0.0.1

Ce script boucle en attendant que la commande ifconfig lui fournisse une ligne commençant par eth0. Ensuite elle configure l’adresse IP de cette interface avec l’adresse IP 192.168.3.152. Il s’agit d’une adresse que j’ai choisie arbitrairement car elle convient au sous-réseau de mon bureau. Vous devrez la modifier pour qu’elle corresponde à votre environnement.

Pour faire bonne mesure, nous initialisons également l’interface loopback avec l’adresse standard 127.0.0.1.

Lorsque l’on teste le script en redémarrant la carte, celle-ci se met à répondre aux pings envoyés depuis une autre machine.

Service de connexion telnet

Le premier service que nous allons mettre en œuvre est le démon telnetd intégré dans Busybox. Celui-ci a été compilé précédemment, et il nous suffit de rajouter son lancement dans le script de démarrage.

Le serveur telnetd permet à un client d’initier une connexion TCP/IP, puis il lance l’application /bin/login pour valider les permissions de l’utilisateur. Toutefois, nous n’avons créé aucun compte pour le moment aussi allons nous demander explicitement à telnetd de démarrer directement un shell, sans authentification supplémentaire. Naturellement ceci ne doit être utilisé qu’à des fins de tests sur un réseau privé. Ajoutons donc la ligne suivante à la fin du script de démarrage.

telnetd -l /bin/sh

Une dernière étape s’impose : le démon telnetd utilise les pseudo-terminaux Unix pour gérer la communication avec le client telnet. Pour cela, il doit ouvrir le fichier spécial /dev/pts/n, n étant un numéro fourni par le kernel. Pour que ce fichier soit disponible, nous pouvons demander au noyau de monter sur /dev/pts un pseudo-système de fichiers spécial nommé devpts. Cela s’obtient en ajoutant les lignes suivantes en début de script, juste après avoir remonté l’arborescence de la racine.

mkdir /dev/pts
mount none /dev/pts  -t devpts

Redémarrons notre Pandaboard, et vérifions le fonctionnement depuis un autre poste.

[~]$ ping 192.168.3.152
PING 192.168.3.152 (192.168.3.152) 56(84) bytes of data.
64 bytes from 192.168.3.152: icmp_req=1 ttl=64 time=0.770 ms
64 bytes from 192.168.3.152: icmp_req=2 ttl=64 time=109 ms
64 bytes from 192.168.3.152: icmp_req=3 ttl=64 time=0.835 ms
Ctrl-C
[~]$ telnet 192.168.3.152
Trying 192.168.3.152...
Connected to 192.168.3.152.
Escape character is '^]'.

/ # cat /proc/cpuinfo 
Processor       : ARMv7 Processor rev 2 (v7l)
processor       : 0
BogoMIPS        : 2007.19
[...]
Hardware        : OMAP4 Panda board
Revision        : 0020
Serial          : 0000000000000000
/ # Ctrl-D
Connection closed by foreign host.
[~]$

L’utilisation du protocole Telnet est très peu recommandée, car il n’y a aucune sécurité dans la transmission des données – ni dans celle des mots de passe. Aussi, on préfère généralement assurer la connexion sur un système Linux en employant le protocole SSH (Secure Shell) avec lequel non seulement les mots de passe mais également tout le contenu de la session est chiffré.

Connexion sécurisée par SSH

Il n’y a pas (encore) d’implémentation du serveur sshd dans Busybox, mais il en existe plusieurs libres (par exemple Open SSH). J’ai choisi d’utiliser plutôt Dropbear, dont l’empreinte mémoire est plus faible.

Téléchargeons la dernière version de Dropbear

[~]$ cd Projets/Panda
[Panda]$ wget http://matt.ucc.asn.au/dropbear/releases/dropbear-0.53.1.tar.bz2
[...]
2011-05-19 00:04:37 (169 KB/s) - «dropbear-0.53.1.tar.bz2» sauvegardé [1577227/1577227]
[Panda]$ tar -xjf dropbear-0.53.1.tar.bz2 
[Panda]$ cd dropbear-0.53.1
[dropbear-0.53.1]$

Ajoutons dans notre PATH le chemin permettant d’atteindre le cross-compiler (arm-linux-gcc).

[dropbear-0.53.1]$ export PATH=$PATH:/cross-arm-linux/usr/bin/
[dropbear-0.53.1]$

Puis préparons la compilation via le script configure. Nous lui indiquons dans la variable host le préfixe à ajouter devant les noms des outils de la toolchain pour réaliser la compilation croisée. Sur ma machine, le package zlib-devel est absent, aussi je désactive cette option non indispensable.

[dropbear-0.53.1]$ ./configure --host=arm-linux --disable-zlib
configure: WARNING: If you wanted to set the --build type, don't use --host.
    If a cross compiler is detected then cross compile mode will be used.
checking for arm-linux-gcc... arm-linux-gcc
[...]
configure:
configure: Now edit options.h to choose features.
[dropbear-0.53.1]$

Les options par défaut de options.h me satisfaisant, je démarre la compilation :

[dropbear-0.53.1]$ make
[...]
arm-linux-gcc  -o dropbearconvert dbutil.o buffer.o dss.o bignum.o signkey.o rsa.o random.o queue.o atomicio.o compat.o  fake-rfc2553.o  dropbearconvert.o keyimport.o libtomcrypt/libtomcrypt.a libtommath/libtommath.a -lutil
[dropbear-0.53.1]$

L’utilitaire scp permet de copier des fichiers facilement d’une machine à l’autre, nous devons le compiler séparément.

[dropbear-0.53.1]$ make scp
[...]
arm-linux-gcc  -o scp scp.o progressmeter.o atomicio.o scpmisc.o compat.o
[dropbear-0.53.1]$

Nous allons devoir réinsérer la carte mémoire Micro-SD de la Pandaboard sur le système cible. Par la suite, nous pourrons transférer directement les fichiers par le réseau. Copions déjà les trois fichiers exécutables nécessaires (dropbearkey sert à préparer la clé secrète du serveur SSH).

[dropbear-0.53.1]$ su
Mot de passe :
[dropbear-0.53.1]# cp dropbear /media/root/usr/bin/
[dropbear-0.53.1]# cp dropbearkey /media/root/usr/bin/
[dropbear-0.53.1]# cp scp /media/root/usr/bin/
[dropbear-0.53.1]#

Une connexion par SSH nécessite obligatoirement une identification avec un nom de compte et un mot de passe. Or nous n’avons créé aucun compte sur la Pandaboard. Corrigeons ceci en ajoutant un fichier /etc/passwd qui contient une unique ligne pour le compte root.

[dropbear-0.53.1]# echo "root:hij0peA8cbCDM:0:0:root:/root:/bin/sh" > /media/root/etc/passwd
[dropbear-0.53.1]# umount /media/root/
[dropbear-0.53.1]# umount /media/boot/
[dropbear-0.53.1]# exit
[dropbear-0.53.1]$

Cette ligne contient sept champs séparés par des deux-points. Le premier est le nom du compte, il est suivi du mot de passe crypté, des User IDentifier et Group IDentifier, du nom complet de l’utilisateur, de son répertoire personnel et enfin de son shell de connexion.

Le mot de passe ici est "root". Comment obtenir la chaîne cryptée ? simplement en utilisant l’utilitaire cryptpw contenu dans Busybox. Par exemple, j’avais saisi lors de la première session telnet la commande suivante pour obtenir le cryptage ci-dessus (la chaîne fournie change à chaque appel, elle contient une part aléatoire).

/ # cryptpw root
hij0peA8cbCDM
/ #

Dans le script d’initialisation, il va falloir d’abord générer la clé privée du serveur SSH (chose que l’on ne fait en principe qu’une seule fois), puis lancer le démon proprement dit. On ajoute donc les lignes suivantes.dans /etc/initd.d/rcS

if [ ! -f /etc/dbkey ]
then
    dropbearkey -t rsa -f /etc/dbkey
fi
dropbear -r /etc/dbkey

Naturellement, je vous encourage à regarder les options offertes par ces différentes commandes et à ajuster leur comportement en fonction de vos contraintes. Connectons-nous après avoir redémarré la cible :

[~]$ ssh root@192.168.3.152
The authenticity of host '192.168.3.152 (192.168.3.152)' can't be established.
RSA key fingerprint is 82:49:a3:b7:6e:5e:b2:99:df:6e:a9:45:8c:34:d2:09.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.3.152' (RSA) to the list of known hosts.
root@192.168.3.152's password:  (root)
~ # uname -a
Linux (none) 2.6.39-rc5-cpb #1 SMP Tue May 3 11:14:47 CEST 2011 armv7l GNU/Linux
~ #

Pas très facile de distinguer les commandes saisies sur l’hôte de développement de celles saisies sur la carte cible ? Pas de problème, nous allons rendre le prompt de la cible plus repérable en y ajoutant un fichier /etc/profile qui contient la ligne suivante :

export PS1="[PANDA W]# "

Ce fichier est lu par le shell lors d’une connexion sur le système. La variable d’environnement PS1 correspond au prompt du shell, le W étant remplacé par le nom du répertoire courant. Déconnectons-nous puis ré-établissons la connexion

 # exit
Connection to 192.168.3.152 closed.
[~]$ ssh root@192.168.3.152
root@192.168.3.152's password: (root)
[PANDA /root]#

Le mot « PANDA » nous permettra de distinguer le shell de la cible de celui de l’hôte de développement.

Transferts de fichiers par SCP

Pour pouvoir transférer des fichiers directement en employant SCP (Secure Copy), un descendant amélioré et sécurisé de RCP (Remote Copy), il faut que le démon dropbear puisse trouver l’exécutable scp. Pour cela, nous allons initialiser la variable d’environnement PATH correctement dans le script de démarrage /etc/init.d/rcS. Insérons la ligne suivante avant l’invocation de dropbear

export PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin

Aucune importance si certains répertoires n’existent pas, ils seront ignorés lors des recherches d’exécutables. Profitons-en également pour ajouter la même ligne dans le fichier /etc/profile (disponible ici). Puis re-démarrons la carte Pandaboard. Une fois le boot terminé, nous pouvons envoyer un fichier depuis l’ordinateur hôte.

[~]$ echo "ESSAI DE TRANSFERT" > mon-fichier
[~]$ scp mon-fichier root@192.168.3.152:/root/ 
root@192.168.3.152's password: (root)
mon-fichier                                                                                                                        100%   19     0.0KB/s   00:00
[~]$ ssh root@192.168.3.152
root@192.168.3.152's password: (root)
[PANDA /root]# ls /root
mon-fichier
[PANDA /root]# cat /root/mon-fichier
ESSAI DE TRANSFERT
[PANDA /root]#

L’utilitaire scp peut s’employer dans les deux sens, la syntaxe est la suivante :

scp fichiers-locaux...  utilisateur@adresse-distante:/repertoire-distant/

ou

scp utilisateur@adresse-distante:/repertoire/distant/fichiers...  /repertoire/local

Naturellement, à ce stade il vous est possible de créer des comptes utilisateurs avec des droits limités et des mots de passe solides, et de supprimer la connexion root (ainsi bien entendu que celle par telnet). Nous pouvons à loisir nous connecter sur notre Pandaboard, et y transférer des fichiers. Terminons cette première partie sur le réseau en installant un petit service simple mais efficace : le serveur HTTP.

Mise en œuvre d’un serveur Web

L’utilisation d’un petit serveur web sur un système embarqué n’est pas rare, bien au contraire. Il est fréquent de disposer d’une interface HTTP pour paramétrer le système, récupérer des statistiques d’exécution, visualiser des états, etc. À tel point qu’il existe de nombreux projets concurrents disponibles pour ce genre de serveur. J’en retiendrai trois principaux.

  • Apache : le serveur HTTP de référence, utilisé par plus de la moitié des sites Web. Très complet, très modulaire, interfaçable avec de nombreux langages (Shell, PHP, Python, Perl, etc.). Sauf exception, je préfère le réserver à des serveurs dédiés sur Internet.
  • Lighttpd : serveur destiné à l’embarqué, il n’implémente pas toutes les fonctionnalités de sécurité d’Apache. Il est facilement interfaçable avec des modules extérieurs (tout particulièrement PHP) via une interface CGI.
  • Busybox : la présence d’un petit démon httpd au sein des applets de Busybox simplifie énormément la mise en œuvre d’un service HTTP simple. Nous allons l’utiliser immédiatement.

Il nous faut tout d’abord transférer sur la cible un fichier HTML que nous copierons dans un répertoire dédié au service HTTP. Commençons par créer le répertoire.

[PANDA /root]# mkdir /home/www
[PANDA /root]#

Puis transférons le petit fichier index.html que vous pouvez trouver ici.

[~]$ scp index.html root@192.168.3.152:/home/www/
root@192.168.3.152's password:
index.html                                               100%  199     0.2KB/s   00:00
[~]$

Enfin ajoutons la ligne suivante à la fin du script de démarrage /etc/init.d/rcS

httpd -f /home/www/

Après reboot de notre carte, essayons de joindre son adresse IP depuis un navigateur web sur notre réseau local en saisissant directement http://192.168.3.152 dans la barre d’URL.

Capture d'écran du navigateur connecté sur la carte Pandaboard

Conclusion

Nous avons ajouté plusieurs fonctionnalités facilement sur notre système embarqué, principalement en éditant le fichier /etc/init.d/rcS (dont voici la nouvelle version) car la plupart des services sont déjà compilés dans Busybox. Il y a toutefois quelques limites à ce système, que nous essayerons de dépasser dans les prochains articles :

  • nous n’avons initialisé que l’interface Ethernet, mais il existe une interface Wifi sur la Pandaboard ;
  • nous n’avons pas essayé de faire de routage ou de résolution de nom (par exemple pour accéder à Internet depuis la Pandaboard) ;
  • l’initialisation a été faite de manière statique avec une adresse attribuée manuellement. Bien que cette approche soit classique dans l’embarqué, on peut préférer utiliser une affectation dynamique d’adresse (en employant par exemple le protocole DHCP) ;
  • notre service Web, bien que fonctionnel est vraiment minimal. Il serait intéressant de l’étendre à l’aide de scripts CGI, voire d’utiliser un serveur un peu plus puissant (par exemple Lighttpd) ;
  • enfin, d’autres services réseau peuvent être intéressant à implémenter : citons par exemple FTP pour un transfert de fichiers plus connu que SCP,  NTP ou PTP pour configurer l’heure système de la carte, SNMP pour superviser des états à distance, etc.

Nous continuerons ces expériences dans de prochains articles…

8 Réponses

  1. Chriss dit :

    Bonsoir,
    oui c’est encore moi.
    Dites le moi si je pose trop de question.
    Je continue le dev sur cette magnifique carte qu’est la pandaboard. Pas de problème pour l’instant. J’ai seulement quelques questions :
    1) Quand je me connecte en shh depuis windows via putty, seules les commande du répertoir bin sont disponible pour l’auto-complétion. Pour pouvoir exécuter une commande telle « ifconfig » je dois taper « /sbin/ifconfig ». N’y aurait il pas un lien avec le shell de connexion ?

    2) Comment peut-on accéder au LEDs présentes sur la carte ?

    Merci d’avance.

    • cpb dit :

      Bonjour,

      Pour le premier point (commandes de /sbin inacessibles sans le chemin d’accès), la solution est simple : il suffit d’ajouter un fichier /etc/profile qui initialise la variable d’environnement PATH. Ce fichier sera interprété par le shell au moment de la connexion. Par exemple on peut y trouver :
      # /etc/profile:

      # Configurer les chemins de recherche des exécutables
      export PATH=/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/usr/local/sbin
      # Configurer le prompt
      export PS1='(PANDA)[`basename $PWD`]$ ‘
      (Attention aux « quotes » et « backquotes » dans la valeur de PS1).

      Pour la seconde question, (accéder aux LEDs) il faut recompiler le noyau (ici un 3.0.0-rc7) en activant les options

      Menu « Devices Drivers » — Sous-Menu « LED Support »
      Menu « Devices Drivers » — Sous-Menu « LED Support — Option « LED Support for GPIO connected LEDs »
      Menu « Devices Drivers » — Sous-Menu « LED Support — Option « Platform device bindings for GPIO LEDs »
      Menu « Devices Drivers » — Sous-Menu « LED Support — Option « LED Trigger support »
      Menu « Devices Drivers » — Sous-Menu « LED Support — Option « LED Timer Trigger »
      Menu « Devices Drivers » — Sous-Menu « LED Support — Option « LED Heartbeat Trigger »
      Menu « Devices Drivers » — Sous-Menu « LED Support — Option « LED GPIO Trigger »

      Après compilation, les deux LEDs sont accessibles via les répertoires /sys/devices/platform/leds-gpio/leds/pandaboard::status1 et ...::status2.
      Par défaut, la LED 1 (la plus éloignée du support MMC) est programmée par le trigger « heartbeat » simulant un battement de coeur. Pour le désactiver
      (PANDA)[/]$ cd /sys/devices/platform/leds-gpio/leds/
      (PANDA)[leds]$ echo none > pandaboard::status1/trigger
      (PANDA)[leds]$

      Allumer et éteindre la LED 1 :
      (PANDA)[leds]$ echo 1 > pandaboard::status1/brightness
      (PANDA)[leds]$ echo 0 > pandaboard::status1/brightness

      Activer un timer sur la LED 2.
      (PANDA)[leds]$ echo timer > pandaboard::status2/trigger
      (PANDA)[leds]$

      Par défaut, c’est un trigger carré (autant allumé qu’éteint), battant à la seconde. On peut modifier ses paramètres (les valeurs sont en millisecondes)
      (PANDA)[leds]$ echo 10 > pandaboard::status2/delay_on
      (PANDA)[leds]$ echo 100 > pandaboard::status2/delay_off

      Je récapitulerai ces manips dans un petit article prochainement.

  2. Xav dit :

    Bonjour,

    Je poursuis vos tutoriaux sur la Pandaboard avec beaucoup d’attention, mais j’ai néanmoins quelques erreurs…
    La dernière en date étant un fameux:
    /bin/sh: dropbear : command not found

    J’ai vérifié sur le PATH, le répertoire est bien inclus…

    Pire, j’ai la complétion automatique, mais toujours « not found », et lorsque je fais le PATH complet pour y acceder, c’est pareil.

    Auriez-vous une idée sur ce genre de problème?

    Merci d’avance,
    Xavier

    • cpb dit :

      Bonjour,

      Je suppose que le message apparaît au moment de l’exécution du script /etc/init.d/rcS ?
      Si c’est bien le cas, deux possibilités : initialiser manuellement la variable PATH au début du script avec quelques chose comme

          [...]
          PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin
          [...]
      

      ou indiquer systématiquement les chemins d’accès complets comme /usr/bin/dropbear.

      Dernière remarque : le fichier dropbear se trouve bien dans /usr/bin ?

      • Xav dit :

        Bonjour,

        Merci de votre réponse si rapide!

        J’ai beau faire le chemin d’accès complet, toujours le même message…
        J’ai fais un test avec un simple « hello world » et c’est identique.

        Je vais essayer de recompiler mon système de fichiers, on ne sait jamais!

        Xavier

        • cpb dit :

          Je ne comprends pas très bien, rien ne fonctionne à part Busybox ?

          Vous avez bien compilé dropbear et le hello-world avec la toolchain croisée ?

  3. Xav dit :

    Oui, il n’y a rien qui fonctionne à part Busybox. J’ai bien vérifié à l’aide d’un « file dropbear », et c’est bien un exécutable ARM, créé à partir d’une cross compil…Mystère mystère!

    • cpb dit :

      Juste une idée en passant : il manque peut-être une bibliothèque sur la cible. Il faudrait vérifier à l’aide de arm-linux-ldd quelles sont les libraries nécessaires pour l’exécutable et s’assurer qu’elles sont toutes présentes dans le répertoire /lib de la cible ou dans un répertoire mentionné dans la variable d’environnement LD_LIBRARY_PATH au moment de l’exécution.

URL de trackback pour cette page