Yohann Martineau, blog

Posts tagged embedded systems

Boot coreboot, FILO and a tiny debian

2012-04-29 19:27:38

I'm playing with open source bios software coreboot. To boot this opensource bios, I use qemu. I was bored of this default SEAbios prompt at virtual machine boot. So I decided to customize a bit my way to boot.

Actually, coreboot is just a piece of code that initialize hardware, it does not make a choice amongst bootable devices to start system. This task is performed by a payload. Actually, it's a payload for coreboot, but it's not the last payload we'll meet. Coreboot supports several payloads: SEAbios, FILO, custom linux, etc. Here, I will show how to install a FILO payload for coreboot and boot a tiny debian from this payload.

FILO is a bootloader that can read files on a local file system and use an image on a local file system to load an OS. So, after starting qemu, the boot sequence is: coreboot => FILO => tiny debian.

The first step is to retrieve coreboot and FILO. Actually, FILO has a dependency on libpayload, which is a library inside coreboot source code. So the compilation order will be: libpayload, FILO and coreboot.

Let's first create a root folder:

mkdir coreboot
In this directory, download coreboot source code:
cd coreboot
svn co svn://coreboot.org/coreboot/trunk coreboot-svn
We download FILO in coreboot-svn/payloads as it seems to be simpler to compile from here.
cd coreboot-svn/payloads
svn co https://svn.coreboot.org/filo/trunk/filo

Now, configure, build and install libpayload:

cd libpayload
make defconfig
make
make DESTDIR=../filo/build install
Now come back in filo folder and configure filo:
cd ../filo
make menuconfig
Use default options. You will see two make menuconfig interfaces, keep default options for both. You can now compile FILO:
make

Configure coreboot:

make menuconfig
Enter payload menu, choose "Add a payload", An ELF executable payload. Select your filo binary file (filo.elf) in "Payload path and filename"

Compile coreboot, compilation instructions can be found in bottom links:

make

My qemu version is a locally compiled one, not the latest one, but any reasonably recent qemu version should work.

Create tiny debian:

~/programs/qemu-0.14.1-local/bin/qemu-img create -f raw disk.img 2G
/sbin/mkfs.ext2 -F disk.img
su
# mkdir /mnt/rootfs
# mount -o loop disk.img /mnt/rootfs/
# mkdir /mnt/rootfs/boot
# cp /boot/vmlinuz-2.6.32-5-686 /mnt/rootfs/boot/vmlinuz
# cp /boot/initrd.img-2.6.32-5-686 /mnt/rootfs/boot/initrd
# apt-get install debootstrap
# debootstrap --arch i386 squeeze /mnt/rootfs/ http://ftp.debian.org/debian/
# umount /mnt/rootfs/
this listing:
  1. creates a qemu empty disk,
  2. format this disk to ext2 file system,
  3. as root, mount qemu disk locally,
  4. copy linux kernel and its temporary file system from real debian install to this new tiny boot file system,
  5. install debootstrap (first time only, of course), this tool creates tiny debian images using debian version in parameter. It will load packages from internet, you may have to be patient for this one,
  6. unmount cleanly this new file system.

start qemu:

~/programs/qemu-0.14.1-local/bin/qemu -bios coreboot-svn/build/coreboot.rom -hda disk.img -nographic

To start debian, in FILO, use:

root (hd0)
kernel /boot/vmlinuz root=/dev/sda initrd=/boot/initrd console=ttyS0
boot
you may have to type Enter twice to see all feedback. Debian automatically renames /dev/hda to /dev/sda, this is the reason why we provide this root.

Once booted, you can see a debian root prompt!

Links, sources

Permanent link
linux, embedded systems, debian, english

Comments

Compiler un firmware de clubinternet box

2009-10-29 14:48:36
Date originale : 5 février 2007

Bonjour,
voici un petit tutorial pour compiler un firmware de clubinternet box, et ainsi pouvoir peronnaliser les fonctions de sa boîte.

Les différentes étapes à suivre sont les suivantes :

  • récupérer les sources du firmware de la clubinternet box (dans mon cas le modèle est AH4222, mais celà devrait être assez proche pour un modèle AH4021),
  • installer la chaîne de compilation fournie,
  • corriger les petites erreurs des sources fournies,
  • compiler les sources et créér une image de système de fichier à flasher sur la ROM de la boîte,
  • transférer cette image sur la boîte.
Cet article décrit la marche à suivre pour compiler ces sources depuis un système GNU/Linux, plus particulièrement Debian Etch.

Obtention des sources

Pour pouvoir compiler les sources, il faut d'abord les obtenir les sources du firmware de la clubinternet box sont disponibles ici. Les versions du firmware doivent à priori évoluer souvent, donc il est possible que ce lien ne marche pas éternellement. En revanche, lorsque ces sources sont mises à disposition du public, une annonce est effectuée sur le forum technique de club-internet, dans la rubrique "Modem ADSL et Téléphonie clubinternet.box et AH-4021". Cette anonce est acutellement intitulée "Code source du firmware Hitachi (V44)", elle contient un lien vers les sources du firmware.

L'accueil des forums de club-internet est accessible ici. Attention, ces sources font quand même environ 84Mo, prévoir un peu de temps pour les télécharger, donc.

Deuxième étape : exploration du contenu de cette archive.

Cette archive contient elle-même deux autres archives et un script d'installation. Une des deux archives (bcm963xx_AH4222.01.2.01L.300L01.V44-08_consumer.tar.gz) contient véritablement le code source du firmware et la seconde archive (bcm963xx_uclibc_crosstools_3.4.2_0.9.27.tar.gz) contient la chaîne de compilation (uclibc) nécessaire pour compiler les sources du firmware avec la bonne cible.

La chaîne de compilation est fournie sous forme de deux paquets rpm, si vous utilisez une distribution gerrant directement les rpm (Mandriva, RedHat, Suse, etc.) vous pouvez vous contenter de lancer le script d'installation en root. L'installation à partir du script d'installation "consumer_install" va créér deux répertoires sous /opt. Si, en revanche vous avez une distribution utilisant des paquets au format debian (Debian, Ubuntu, etc.), comme c'est mon cas, il va falloir décompresser l'archive contenant les deux rpms, puis transformer ces paquets RPM en paquets deb.

Pour cela, on peut utilser le programme alien accouplé à rpm pour générer des paquets .deb à partir de paquets .rpm. La commande suivante, lancée en root permet donc d'installer les programmes nécessaires :

# apt-get install alien rpm

Ensuite pour convertir les paquets il suffit de lancer alien avec en paramètre le paquet à convertir.

# alien uclibc-crosstools-mips.i386.rpm
# alien -scripts uclibc-crosstools-common.i386.rpm

Attention : il faut rajouter l'option -scripts pour le paquet uclibc-crosstools-common.i386.rpm car ce paquet contient des scripts de post-installation, de pré-installation, ou d'un autre type, mais il est nécessaire d'inclure ces scripts dans le paquet généré (pas fait par défaut).

Deux paquets sont normalement disponibles au format .deb maintenant. Pour les installer, il suffit donc de lancer la commande suivante en root :

# dpkg -i *.deb

Les sources du firmware n'utilisent pas directement l'emplacement par défaut de la chaîne de compilation, il est donc nécessaire de rajouter un lien vers la chaîne :

# ln -s /opt/toolchains /opt/toolchains_3_00
Victoire ! La chaîne de compilation est désormais installée, et opérationnelle !

Patchs à effectuer

Avant de se casser les dents sur la compilation, mieux vaut effectuer quelques modifications dans les sources fournies.

Tout d'abord, il est nécessaire de patcher la génération de configuration du noyau linux. Il faut modifier le fichier suivant :

/opt/bcm963xx_router/kernel/linux/scripts/kconfig/mconf.c
Dans ce fichier, il faut remplacer toutes les occurences de current_menu par un autre nom non déjà pris, par exemple current_mconf_menu.

Ensuite, il faut patcher le système de gestion de la configuration de la clubinternet box.

Dans le fichier :

/opt/bcm963xx_router/userapps/broadcom/cfm/util/system/syscall.c
Supprimer les références à sha1.h, c'est à dire :
  • supprimer la ligne #include "sha1.h"
  • supprimer tout ce qu'il y a après la ligne :
    /********************** end base64 decode and encode functions **********************/
Cela correspond aux méthodes liées à sha1.h dont l'implémentation n'est pas fournie.

Compilation

Ouf, la compilation va maintenant pouvoir commencer.

Les cibles disponibles pour la compilation sont présentes dans le répertoire targets des sources du firmware, désormais installées dans /opt/bcm963xx_router. Dans notre cas, il y a un répertoire 96348GWV ou similaire qui nous donne le nom de la cible à passer en paramètre à la compilation.

La commande à taper (toujours en root) pour lancer la compilation est donc la suivante :

# make PROFILE=96348GWV
Là, on croise bien fort les doigts et quelques minutes plus tard, une image de disque ROM a été générée et est prête à être transférée dans la mémoire de la clubinternet box. Si la compilation s'est bien passée, un message l'indique en donnant le nom de l'image du système de fichier à ralonge qui a été générée. Dans mon cas le nom de l'image générée est la suivante :
bcm96348GWV_fs_kernel_AH4222.01.2.01.300L01.V44-08.mgcp.dspApp3341_fxo.LE9500-070204_1656

Transfert de l'image

Maintenant que nous avons notre image, le plus dûr à été effectué. Il reste tout de même à installer sur sa machine un serveur tftp pour pouvoir transférer l'image sur la boîte. En effet, lorsque la boîte effectue ses mises à jour en tant normal, elle transfert son image en utilisant un client tftp un peu allégé. Ce client récupère en tant normal l'image sur le site suivant : tftp-ht.voip.club-internet.fr mais nous allons désormais lui faire utiliser notre machine, sur laquelle vient d'être générée une image toute neuve.

Sous debian, il suffit d'utiliser la commande apt-get install tftpd pour installer un serveur tftp, il doit certainement y avoir l'équivalent pour les distributions au format rpm. La racine du serveur tftp sous debian se trouve dans /srv/tftp, il suffit donc de copier l'image générée dans ce répertoire.

Ensuite on peut se connecter via telnet à la clubinternet box :

$ telnet 192.168.1.1
L'utilisateur est root, et le mot de passe est clubadmin. Une fois connecté, une invite de commande commançant par > s'affiche. Il est désormais possible de transférer l'image et de la flasher immédiatement avec la commande suivante :
> tftp -g -f bcm96348GWV_fs_kernel_AH4222.01.2.01.300L01.V44-08.mgcp.dspApp3341_fxo.LE9500-070204_1656 192.168.1.2
-g est l'option correspondant à get
-f pour spécifier le nom du fichier distant à transférer et l'adresse de la machine sur laquelle on est à passer à la fin (éventuellement à adapter)

Si vous vous trompez de fichier ou que vous ne spécifiez pas une image valide à transférer, la clubinternet box va le détecter et à son prochain reboot, elle téléchargera l'image du firmware depuis le site de club-internet.

Après le "flashage", la boîte redémarre, il faut lui laisser quelques minutes, et si après ces quelques minutes vous pouvez vous connecter à internet, c'est gagné ! vous avez réussi à installer votre image de système de fichier sur la boîte !

Personnaliser sa boîte

Maintenant que nous savons compiler notre image et la transférer sur la boîte, nous allons (enfin) pouvoir commencer à faire des choses amusantes avec la boîte. Nous allons réalser les étapes suivantes :

  • écrire un "Hello world" en c,
  • le compiler au bon format,
  • placer le binaire au bon endroit,
  • recompiler l'image,
  • la transférer,
  • tester notre super programme.
Ecrire un fichier helloworld.c :
#include

int main() {
  printf("Hello, world!\n");
  return 0;
}
C'est rudimentaire, mais très utile pour pouvoir effectuer des tests simples.

Maintenant, nous pouvons compiler notre premier programme avec la chaîne de compilation :

/opt/toolchains/uclibc-crosstools/bin/mips-uclibc-gcc helloworld.c
Nous avons donc maintenant un fichier binaire a.out. Ce fichier est au format MIPS, nous pouvons le vérifier avec la commande suivante :
# file a.out
a.out: ELF 32-bit MSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked (uses shared libs), not stripped

Une fois que nous avons ce fichier binaire exécutable sur la clubinternet box, nous pouvons le placer au bon endroit dans l'arborescence du système de fichier utilisé pour créér l'image de disque ROM :

# cp a.out /opt/bcm963xx_router/targets/fs.src/usr/bin
les fichiers exécutables que l'on génère sont à placer dans /usr/bin dans /opt/bcm963xx_router/targets/fs.src et non dans /bin, car ces programmes ne concernent pas le fonctionnement du système directement. Et surtout des vérifications sont effectuées lors de la compilation sur la suppression des entêtes et autres données "inutiles" (strip) dans le programme sous forme de fichier binaire.
Maintenant, tout est prêt pour regénérer l'image de disque ROM (une nouvelle image est générée et l'ancienne n'est pas écrasée). Voir plus haut. Idem pour le transfert de l'image.

Une fois que l'image a été générée, on peut déjà vérifier que rien n'a été cassé en essayant de se connecter à internet. Si tout fonctionne, nous pouvons continuer et tester notre programme.
Il faut donc à nouveau se connecter sur la boite (telnet 192.168.1.1 root/clubadmin). Mais maintenant que l'invite en > apparaît, nous allons lancer un shell pour pouvoir exécuter notre programme. Il suffit de taper la commande suivante :

> sh

BusyBox v1.00 (2007.02.04-15:52+0000) Built-in shell (msh)
Enter "help" for a list of built-in commands.

#
Nous pouvons maintenant enfin lancer notre programme hors du commun avec la commande suivante :
# /usr/bin/helloworld
Hello, world!
#
Victoire, nous pouvons exécuter le code que nous voulons sur la boîte !!!

Remarques

Un client http (wget) est directement fourni sur la boîte, nous aurions donc pu simplement compiler le programme, le mettre sur un serveur web et le transférer avec wget a.out en le plaçant dans la partition /var accessible en écriture sur la boîte, puis le rendre exécutable (chmod 755) et le lancer directement. En revanche, le fait d'insérer notre programme dans /var limite sa taille fortement (en général, entre 50 et 150 ko sont disponibles dans /var), alors que la ROM de la club internet box peut contenir jusqu'à 4,2Mo de données. Mais surtout /var n'est pas l'endroit adequat pour l'exécution des programmes sous linux.

Voilà, j'espère que ce petit tutorial aura pu vous aider...

Permanent link
linux, internet, embedded systems, development, français

Comments