2010
10.23

Vouloir développer un noyau de système d’exploitation pour une machine dont on ne connait presque rien, c’est une chose. Le faire, c’en est une autre. Jusqu’à aujourd’hui je ne connaissais rien du tout de l’intérieur de la Fonera+, comment booter un système, et toutes ces choses nécessaires pour pouvoir commencer à effectivement coder un noyau. Fort heureusement, on trouve beaucoup de documentation sur le net, notamment sur les wikis des firmwares alternatifs de routeur. Du coup, j’ai pu glaner un grand nombre d’informations que je vais résumer dans cet article.

Commençons par le matériel qui se trouve dans la Fonera+. La page de wiki d’OpenWRT parle en détail du matériel de la Fonera normale, et d’après une comparaison sur Tom’s Hardware la seule différence entre la Fonera et la Fonera+ est dans le contrôleur Ethernet. Le CPU est un MIPS 4KEc, donc un CPU MIPS 32 bits qui fonctionne aussi bien en little endian qu’en big endian. D’ailleurs, comme l’indique le wiki officiel de Fon, leur firmware officiel tourne en big endian alors qu’OpenWRT tourne normalement en little endian. Le routeur est doté de 16 Mio de RAM et 8 Mio de Flash. Le reste nous importe peu pour le moment.

Pour exécuter notre noyau sur la Fonera+, il faut trouver un moyen de le transférer sur le routeur puis de lui faire exécuter le code. Sur un PC classique, le BIOS exécute par défaut le premier secteur du premier disque dur pour booter l’OS. En général, il y a un intermédiaire nommé le bootloader (dont GRUB, NTLDR, LILO et quelques autres sont des exemples) qui se charge de booter un noyau qui est sur une partition du disque et pas dans le premier secteur (car c’est plus pratique pour tout le monde que le noyau soit un fichier comme les autres). La Fonera+ a elle aussi un bootloader, nommé RedBoot. Il boote par défaut sur un fichier de la ROM, mais il peut faire plein d’autres choses. Voyons tout d’abord comment on peut y accèder et le contrôler.

On peut rentrer dans la console série de RedBoot de deux manières : via un port série que l’on bricole et que l’on branche sur des bornes de la carte de la Fonera+ (vraiment pas pratique et je suis pas très bricolo), ou simplement en ethernet ! Par défaut, RedBoot sur la Fonera+ est accessible via telnet sur le port 9000 et l’IP 192.168.1.1 pendant 2s avant de démarrer l’OS par défaut de la Fonera+. En s’y connectant pendant les 2s on peut interrompre le chargement de l’OS (via un simple ^C) et rentrer dans la console de RedBoot qui permet de faire tout plein de choses. Sous Linux, en supposant que le routeur est branché directement via un cable ethernet à l’interface eth0 de la machine, la marche à suivre exacte est la suivante :

  • Configurer le réseau sur la machine pour faire transiter tout 192.168.1.0 vers le port ethernet qui nous intéresse : sudo ip route add 192.168.1.0/24 via eth0
  • Débrancher l’alimentation de la Fonera+ pour lui faire subir un reboot complet
  • Créer un fichier ~/.telnetrc via les commandes suivantes afin de configurer telnet en mode bufferisé par ligne (nécessaire pour que le ^C fonctionne !) : echo -e "192.168.1.1\n\tmode line" >> ~/.telnetrc
  • Préparer la machine à se connecter à la Fonera+ dès qu’elle sera accessible : sudo arping -f 192.168.1.1; telnet 192.168.1.1 9000
  • Brancher l’alimentation de la Fonera+ et se préparer à faire ^C dès que la connexion telnet sera établie.

Si tout se passe bien, il devrait s’afficher quelque chose ressemblant à ceci sur la machine locale : ARPING 192.168.1.1 from 192.168.2.202 eth0
Unicast reply from 192.168.1.1 [00:18:84:A0:BF:D0] 1.048ms
Sent 8 probes (8 broadcast(s))
Received 1 response(s)
Trying 192.168.1.1...
Connected to 192.168.1.1.
Escape character is '^]'.
== Executing boot script in 1.030 seconds - enter ^C to abort
^C
RedBoot>

Nous sommes donc dans la console de RedBoot. À partir de là, on peut faire plein de choses utiles dont je ne parlerai pas forcèment (pour ça il y a la commande help). Parmi ce qui nous intéresse, on peut afficher la configuration de RedBoot via la commande fconfig -l -n. Sur ma Fonera+, ça renvoie ceci : RedBoot> fconfig -l -n
boot_script: true
boot_script_data:
.. fis load -l vmlinux.bin.l7
.. exec
boot_script_timeout: 2
bootp: false
bootp_my_gateway_ip: 0.0.0.0
bootp_my_ip: 192.168.1.1
bootp_my_ip_mask: 255.255.255.0
bootp_server_ip: 192.168.1.254
console_baud_rate: 9600
gdb_port: 9000
info_console_force: false
net_debug: false

On peut remarquer là dedans les choses suivantes :

  • On peut redéfinir le script RedBoot lancé au démarrage du routeur. Quand on aura un truc qui fonctionne bien, on pourra le faire se lancer automatiquement avec ça.
  • On peut définir un serveur BOOTP. BOOTP, c’est l’ancêtre de DHCP, et le principe est bien expliqué sur la page Wikipédia du protocole. C’est très bon, ça veut dire qu’on peut potentiellement faire des tests de boot sans avoir à mettre notre noyau sur la ROM à chaque modification. RedBoot ira simplement demander le noyau sur le réseau et on lui renverra le fichier qui va bien.
  • RedBoot se comporte comme un remote target gdb. Cela signifie qu’on peut utiliser le debugger GDB pour debugger notre noyau pendant qu’il est en fonctionnement sur le routeur. Encore une fois, ça sera très pratique quand on devra programmer notre noyau et qu’on aura des bugs louches.

L’autre commande qui va surement être intéressante, c’est load. D’après sa documentation, elle permet de télécharger un binaire dans la RAM pour ensuite l’exécuter. Pour ça, RedBoot peut utiliser soit le protocole TFTP, soit le protocole HTTP. Apparemment HTTP plante dans la version de RedBoot installée sur la Fonera+, tant pis.

Vu que je suis curieux de voir comment ça marche, j’ai mis en place un serveur TFTP sur ma machine pour faire télécharger un fichier à RedBoot. Pour cela, j’ai créé un fichier rempli de zéros avec dd if=/dev/zero of=dmms.bin count=42, puis je l’ai placé dans le dossier /var/tftpboot. J’ai configuré l’interface eth0 de ma machine en point to point avec la commande sudo ifconfig eth0 192.168.1.2 pointopoint 192.168.1.1 puis j’ai lancé /etc/rc.d/tftpd start pour servir le fichier. Ensuite, sur la Fonera+, j’ai lancé load -h 192.168.1.2 dmms.bin, ce qui a effectivement téléchargé le fichier, mais le format n’est pas reconnu (normal, que des zéros) : RedBoot> load -h 192.168.1.2 dmms.bin
Using default protocol (TFTP)
Unrecognized image type: 0x0

On a donc maintenant une méthode permettant d’exécuter du code sur la bête. La prochaine étape sera d’exécuter quelque chose d’un peu plus utile. Peut-être un hello world ? :-)

Voir aussi :

6 comments so far

Add Your Comment
  1. Moi qui craignais de ne rien comprendre, je trouve ça plutôt accessible pour l’instant. Faut dire que RedBoot te simplifie assez la tâche.

    Par curiosité naïve, qu’est-ce que tu aurais du faire si ce dernier n’avait pas permis charger des binaires via le réseau ?

    • La solution suivante c’était le bricolage : flasher la ROM manuellement pour y installer RedBoot ou un truc du genre. Sur la plupart des routeurs il y a des failles de sécurité qui permettent de faire ça sans ouvrir le routeur (genre « mise à jour du firmware »). Au pire j’avais toujours la solution d’emprunter du matos dans des labos d’EPITA qui touchent un peu à ça :) .

  2. Voleur d’idée de design.

    • En même temps, je t’ai demandé si tu connaissais des bons designs sombres pour WP hier et c’est toi qui me l’a proposé, donc hein.

  3. Salut
    - Pour lancer un firmware depuis la RAM, il faut que tu utilises des fichiers au format ELF.
    C’est un peu plus volumineux en taille que les fichiers de firmware .bin qui sont destinés à être flashés.
    Dans ton fichier ELF se trouve un kernel et un système de fichiers (en RAM uniquement).

    Une fois que ton image correspond à ce que tu veux, tu n’as qu’à recompiler en JFFS2 ou SQUASHFS pour flasher définitivement ta fonera+

    Tu peux aussi lancer directement un kernel depuis RedBoot (les .lzma) , mais ça ne va pas t’avancer a grand-chose, à part outrepasser un kernel foireux en flash ce qui est rare.

    Tu trouveras tous ces fichiers chez OpenWRT: http://downloads.openwrt.org/ (sous-répertoire “atheros” pour les fonera)

    Autrement tu as FONERAM ici : http://www.moliets-bastide.info/post/FONERAM :)
    Ca te permettra de jouer sans casser ta fonera+

    Enjoy !

    • J’ai déjà flashé ma Fonera+ avec OpenWRT en fait. Le but de cette série d’articles est justement de m’amuser à programmer mon propre noyau.

      Pour les fichiers ELF, on peut faire des trucs assez peu volumineux si je ne m’abuse. Je viens de faire un exécutable ELF pour mips32r2-le-eabi et l’overhead d’ELF est de moins de 600 octets par rapport à un .bin avec uniquement le code exécutable (négligeable donc). Si on compte qu’en plus on peut compresser ça en LZMA, la taille ne risque pas de me poser problème avant un moment.

*