Création d’un système complet avec Buildroot

Publié par cpb
Déc 08 2015

Création d'un système complet avec Buildroot 2015-11

[Une version plus récente de cet article est disponible ici]

Le projet Buildroot nous fournit désormais une version de travail trimestrielle et une version annuelle maintenue sur le long terme. Buildroot permet de construire un système embarqué plus traditionnel qu’en utilisant une distribution pré-compilée, et d’ajuster plus finement son contenu. Nous allons l’utiliser pour construire un système personnalisé pour Raspberry Pi.

[5 Novembre 2018: cet article a été mis à jour pour prendre en compte la version « long terme » actuelle de Buildroot. L’ancien article qui parlait de Buildroot 2015.11 est archivé ici.]

Nous allons successivement préparer une chaîne de cross-compilation, construire un système minimal pour vérifier le bon fonctionnement de celle-ci puis générer un système configuré de façon plus personnalisée.

Environnement de travail

Commençons par créer une arborescence de travail qui contiendra tous nos fichiers personnalisés, les répertoires de construction, la chaîne de compilation, etc.

[~]$ mkdir br-tree
[~]$ cd br-tree
[br-tree]$

Au sein de cet environnement, nous allons essayer de respecter l’organisation des fichiers proposée par le projet Buildroot : une arborescence board/ contenant un sous-répertoire pour chaque carte que nous supporterons (ici le Raspberry Pi 3 uniquement). Tous nos fichiers personnalisés se trouveront dans cette sous-arborescence.

[br-tree]$ mkdir -p board/rpi-3/

Nous téléchargeons les sources de la dernière version de Buildroot, les décompressons et entrons dans ce répertoire :

[br-tree]$ wget http://www.buildroot.org/downloads/buildroot-2018.02.7.tar.bz2
[br-tree]$ tar xf buildroot-2018.02.7.tar.bz2
[br-tree]$ cd buildroot-2018.02.7/

Toolchain

J’ai l’habitude de commencer mes projets embarqués par la construction d’une toolchain de cross-compilation. Il s’agit d’obtenir un compilateur – et tous les outils associés – fonctionnant sur la machine de développement (un PC par exemple) et produisant du code pour la plate-forme cible (ici le Raspberry Pi 3).

Il est tout à fait possible de se procurer une toolchain pré-compilée, mais je trouve qu’il est dommage de se priver de cette étape de construction, d’autant que cela nous permet de maîtriser exactement les versions de la bibliothèque C, du noyau, des outils, etc. que nous souhaitons.

Si j’isole cette étape de la production du système complet, c’est qu’elle prend un temps significatif (une vingtaine de minutes sur un petit processeur i7 avec une connexion Internet fibre). La toolchain est donc compilée et installée une fois pour toutes, et ne sera plus modifiée même si nous réitérons autant de génération du système que nous le désirons.

J’ai l’habitude de placer la toolchain dans le répertoire board/<target>/cross.

Pour produire la toolchain, nous demandons une configuration de Buildroot par défaut pour la cible choisie, et l’élaguons pour ne laisser que la production du compilateur et de ses outils. Les configurations par défaut disponibles sont visibles dans le sous-répertoire configs/. Nous choisissons celle pour Raspberry Pi 3.

[buildroot-2018.02.7]$ make raspberrypi3_defconfig
[buildroot-2018.02.7]$ make menuconfig

Voici la liste des modifications apportées :

    • Menu Target options : pas de changement, mais on peut en profiter pour observer et vérifier le support du processeur cible.
    • Menu Build options :
        • Download dir : nous extrayons de l’arborescence de Buildroot ce répertoire dans lequel il stocke les fichiers téléchargés. Ainsi les compilations successives ne nécessiterons pas de nouveaux téléchargements. Nouvelle valeur : $(TOPDIR)/../dl
      • Host dir : l’emplacement où se trouvera la toolchain compilée. Comme indiqué plus haut, j’ai pour habitude de la placer dans le répertoire board/<target>/cross de notre arborescence de travail. Nouveau chemin : $(TOPDIR)/../board/rpi-3/cross
    • Menu Toolchain :
      • C library : c’est un choix qui dépend beaucoup du code métier. La bibliothèque C est un point-clé du système ; c’est elle qui permet d’entrer dans le noyau pour bénéficier de ses services (appels-système). Pour être le plus générique possible, nous choisissons la Gnu C library, un peu plus volumineuse que les autres, mais plus riche également. Nouvelle valeur : glibc
      • Kernel Headers : la compilation de la bibliothèque C nécessite de charger les fichiers headers du noyau afin de connaître ses points d’entrée (voir cet article pour plus de détails). Par défaut Buildroot utilise la même version de noyau que celui qui sera construit pour le système (Linux 4.9.x). Toutefois nous n’allons pas compiler tout de suite de noyau aussi se rabat-il sur la version la plus récente qu’il connaît (Linux 4.15.x) pour produire la libC. Si nous laissons en l’état, une fois que nous aurons compilé tout le système et booterons le Raspberry Pi 3, la GlibC compilée pour un 4.15 refusera de s’initialiser sur un 4.9. et affichera le message « Kernel too old » avant qu’un Kernel Panic se produise puisque le processus init ne peut démarrer. Nouvelle valeur : Linux 4.9.x kernel headers. Le menu Custom kernel headers series disparaît alors.
      • Build cross gdb for the host : en prévision des éventuelles séances de débogage distant du code applicatif, j’ajoute dans la toolchain un débogueur qui fonctionne sur PC mais peut analyser du code au format de la cible. Nouvelle valeur : [*].
    • Menu System configuration :
      • Init system : cette option contient au préalable BusyBox mais nous la désactivons pour pouvoir éliminer ce package. Nouvelle valeur : None
      • Custom scripts to run before creating filesystem images : nous n’allons pas produire de système complet, il ne faut donc pas lancer le script qui finalise l’arborescence avant de créer les images des systèmes de fichiers. Nouvelle valeur : ().
      • Custom scripts to run after creating filesystem images : pour la même raison nous ne lançons pas le script qui assemble les images des systèmes de fichiers pour créer une image complète de la carte microSD pour Raspberry Pi. Nouvelle valeur : ().
    • Menu Kernel :
      • Linux Kernel : nous ne voulons, dans un premier temps, produire que la toolchain et rien d’autre. Nous désactivons cette option. Nouvelle valeur : [ ]
    • Menu Target packages :
      • BusyBox : c’est le seul package initialement présent. Nous le désactivons. Nouvelle valeur : [ ]
    • Menu Filesystem images :
      • ext2/3/4 root filesystem : inutile, nous ne voulons pas de filesystem pour le moment. Nouvelle valeur : [ ]
  • Menu Legacy config options : Je jette toujours un œil à ce menu lorsque j’utilise une nouvelle version de Buildroot avec un fichier de configuration pré-existant car il nous indique les fonctionnalités incompatibles (modifiées, disparues, etc.) entre deux versions.
    Comme nous avons généré un fichier de configuration « from scratch« , ce n’est pas nécessaire ici.

Sauvegardons la configuration et lançons la compilation. Une nouvelle cible de compilation « toolchain » est disponible depuis quelques versions de Buildroot. Je suppose que certaines de nos modifications dans les menus « System configuration« , « Kernel » et « Target Packages » sont redondantes avec cette nouvelle cible mais je préfère les appliquer quand même.

[buildroot-2018.02.7]$ cp .config ../board/rpi-3/buildroot-2018.02-toolchain.config
[buildroot-2018.02.7]$ make toolchain

Après quelques minutes, la compilation se termine avec ces lignes :

	-e 's#@@STAGING_SUBDIR@@#arm-buildroot-linux-gnueabihf/sysroot#' \
	-e 's#@@TARGET_CFLAGS@@#-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Os#' \
	-e 's#@@TARGET_CXXFLAGS@@#-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Os#' \
	-e 's#@@TARGET_FCFLAGS@@#-Os#' \
	-e 's#@@TARGET_LDFLAGS@@##' \
	-e 's#@@TARGET_CC@@#bin/arm-buildroot-linux-gnueabihf-gcc#' \
	-e 's#@@TARGET_CXX@@#bin/arm-buildroot-linux-gnueabihf-g++#' \
	-e 's#@@TARGET_FC@@#bin/arm-buildroot-linux-gnueabihf-gfortran#' \
	-e 's#@@CMAKE_SYSTEM_PROCESSOR@@#armv6l#' \
	-e 's#@@TOOLCHAIN_HAS_FORTRAN@@#0#' \
	-e 's#@@CMAKE_BUILD_TYPE@@#Release#' \
	/home/testing/Build/br-tree/buildroot-2018.02.7/support/misc/toolchainfile.cmake.in \
	> /home/testing/Build/br-tree/buildroot-2018.02.7/../board/rpi-3/cross/share/buildroot/toolchainfile.cmake

Vérifions la toolchain produite :

[buildroot-2018.02]$ cd ..
[br-tree]$ ls board/rpi-3/cross/usr/bin/
arm-buildroot-linux-gnueabihf-addr2line          arm-linux-as
arm-buildroot-linux-gnueabihf-ar                 arm-linux-c++
arm-buildroot-linux-gnueabihf-as                 arm-linux-c++.br_real
arm-buildroot-linux-gnueabihf-c++                arm-linux-cc
arm-buildroot-linux-gnueabihf-c++.br_real        arm-linux-cc.br_real
arm-buildroot-linux-gnueabihf-cc                 arm-linux-c++filt
arm-buildroot-linux-gnueabihf-cc.br_real         arm-linux-cpp
arm-buildroot-linux-gnueabihf-c++filt            arm-linux-cpp.br_real
arm-buildroot-linux-gnueabihf-cpp                arm-linux-elfedit
arm-buildroot-linux-gnueabihf-cpp.br_real        arm-linux-g++
arm-buildroot-linux-gnueabihf-elfedit            arm-linux-g++.br_real
arm-buildroot-linux-gnueabihf-g++                arm-linux-gcc
arm-buildroot-linux-gnueabihf-g++.br_real        arm-linux-gcc-6.4.0
arm-buildroot-linux-gnueabihf-gcc                arm-linux-gcc-6.4.0.br_real
arm-buildroot-linux-gnueabihf-gcc-6.4.0          arm-linux-gcc-ar
arm-buildroot-linux-gnueabihf-gcc-6.4.0.br_real  arm-linux-gcc.br_real
arm-buildroot-linux-gnueabihf-gcc-ar             arm-linux-gcc-nm
arm-buildroot-linux-gnueabihf-gcc.br_real        arm-linux-gcc-ranlib
arm-buildroot-linux-gnueabihf-gcc-nm             arm-linux-gcov
arm-buildroot-linux-gnueabihf-gcc-ranlib         arm-linux-gcov-dump
arm-buildroot-linux-gnueabihf-gcov               arm-linux-gcov-tool
arm-buildroot-linux-gnueabihf-gcov-dump          arm-linux-gprof
arm-buildroot-linux-gnueabihf-gcov-tool          arm-linux-ld
arm-buildroot-linux-gnueabihf-gprof              arm-linux-ld.bfd
arm-buildroot-linux-gnueabihf-ld                 arm-linux-nm
arm-buildroot-linux-gnueabihf-ld.bfd             arm-linux-objcopy
arm-buildroot-linux-gnueabihf-nm                 arm-linux-objdump
arm-buildroot-linux-gnueabihf-objcopy            arm-linux-ranlib
arm-buildroot-linux-gnueabihf-objdump            arm-linux-readelf
arm-buildroot-linux-gnueabihf-ranlib             arm-linux-size
arm-buildroot-linux-gnueabihf-readelf            arm-linux-strings
arm-buildroot-linux-gnueabihf-size               arm-linux-strip
arm-buildroot-linux-gnueabihf-strings            gawk
arm-buildroot-linux-gnueabihf-strip              igawk
arm-linux-addr2line                              m4
arm-linux-ar                                     toolchain-wrapper
[br-tree]$

La toolchain de cross-compilation regroupe tous les outils dont les noms sont préfixés par l’architecture (arm), l’outil de production (buildroot), le système d’exploitation de la cible (linux) et les conventions d’interfaçage binaire entre applications et système (gnueabi). Pour simplifier l’appel des outils, des liens symboliques existent raccourcissant le préfixe pour ne garder que l’architecture et le système d’exploitation. On invoquera donc arm-linux-gcc ou arm-linux-g++ par exemple.

[br-tree]$ board/rpi-3/cross/usr/bin/arm-linux-gcc -v
Utilisation des specs internes.
COLLECT_GCC=/home/testing/Build/br-tree/board/rpi-3/cross/bin/arm-linux-gcc.br_real
COLLECT_LTO_WRAPPER=/home/testing/Build/br-tree/board/rpi-3/cross/bin/../libexec/gcc/arm-buildroot-linux-gnueabihf/6.4.0/lto-wrapper
Cible : arm-buildroot-linux-gnueabihf
Configuré avec: ./configure --prefix=/home/testing/Build/br-tree/buildroot-2018.02.7/../board/rpi-3/cross --sysconfdir=/home/testing/Build/br-tree/buildroot-2018.02.7/../board/rpi-3/cross/etc --enable-static --target=arm-buildroot-linux-gnueabihf --with-sysroot=/home/testing/Build/br-tree/buildroot-2018.02.7/../board/rpi-3/cross/arm-buildroot-linux-gnueabihf/sysroot --disable-__cxa_atexit --with-gnu-ld --disable-libssp --disable-multilib --with-gmp=/home/testing/Build/br-tree/buildroot-2018.02.7/../board/rpi-3/cross --with-mpc=/home/testing/Build/br-tree/buildroot-2018.02.7/../board/rpi-3/cross --with-mpfr=/home/testing/Build/br-tree/buildroot-2018.02.7/../board/rpi-3/cross --with-pkgversion='Buildroot 2018.02.7' --with-bugurl=http://bugs.buildroot.net/ --disable-libquadmath --enable-tls --disable-libmudflap --enable-threads --without-isl --without-cloog --disable-decimal-float --with-abi=aapcs-linux --with-cpu=cortex-a53 --with-fpu=neon-vfpv4 --with-float=hard --with-mode=arm --enable-languages=c,c++ --with-build-time-tools=/home/testing/Build/br-tree/buildroot-2018.02.7/../board/rpi-3/cross/arm-buildroot-linux-gnueabihf/bin --enable-shared --disable-libgomp
Modèle de thread: posix
gcc version 6.4.0 (Buildroot 2018.02.7)

Si l’on souhaite pouvoir invoquer directement le cross-compiler depuis la ligne de commande sans préciser tout le chemin (par exemple pendant une phase de développement de code métier hors Buildroot), on peut éditer le fichier ~/.bashrc afin d’y ajouter à la fin la ligne suivante :

PATH=$PATH:~/br-tree/board/rpi-3/cross/usr/bin/

On peut aussi adopter une autre approche qui consiste à créer un script qui modifie dynamiquement le PATH, script que l’on sourcera (que l’on invoquera en le précédant d’un point) avant chaque session de travail sur le code applicatif.

Système complet

Nous allons construire à présent une image d’un système complet, y compris le noyau, en utilisant la toolchain obtenue précédemment. Il nous faut effacer les fichiers objets, fichiers temporaires, etc. produits auparavant et l’on serait tenté de faire un make clean. Abstenons-nous en néanmoins car cela aurait pour effet d’effacer la toolchain compilée. La solution la plus simple pour éviter les erreurs de manipulation est de supprimer le répertoire de compilation de Buildroot et de décompresser à nouveau l’archive téléchargée.

[br-tree]$ rm -rf buildroot-2018.02.7
[br-tree]$ tar xf buildroot-2018.02.7.tar.bz2 
[br-tree]$ cd buildroot-2018.02.7/
[buildroot-2018.02.7]$

Puis nous préparons une nouvelle configuration, toujours, en partant de celle par défaut.

[buildroot-2018.02.7]$ make raspberrypi3_defconfig
[buildroot-2018.02.7]$ make menuconfig

Passons en revue les menus pour observer ce qu’il faut modifier :

    • Target options : rien à changer
    • Build options :
      • Download dir : configurons le répertoire de téléchargement pour retrouver le précédent. Nouvelle valeur : $(TOPDIR)/../dl
    • Toolchain : plusieurs modifications sont nécessaires pour retrouver la toolchain précédente.
      • Toolchain type : nous souhaitons que Buildroot considère la toolchain comme préexistante, même si c’est lui qui l’a créée auparavant. Nouvelle valeur : External toolchain
      • Toolchain : elle a été compilée spécifiquement. Nouvelle valeur : Custom toolchain
      • Toolchain origin : il n’est pas nécessaire de la télécharger. Valeur conservée : Pre-installed toolchain
      • Toolchain path : le répertoire dans lequel se trouve le sous-répertoire bin de la chaîne de compilation. Nouvelle valeur : $(TOPDIR)/../board/RPI-3/cross/usr
      • External toolchain gcc version : si vous n’avez pas noté ce numéro de version lors de la configuration de la toolchain, vous pouvez l’obtenir en appelant arm-linux-gcc -v comme ci-dessus. Nouvelle valeur : 6.x
      • External toolchain kernel headers series : on peut retrouver le numéro de version si on ne l’a pas noté, mais c’est plus compliqué. Il faut regarder le contenu du fichier ../board/rpi-3/cross/usr/arm-buildroot-linux-gnueabihf/sysroot/usr/include/linux/version.h. On y trouve une valeur LINUX_VERSION_CODE 264581. Il faut convertir ce nombre en hexadécimal, par exemple en saisissant sur la ligne de commande du shell printf '%x\n' 264581. Ceci nous affiche 40985 qui représente chiffre par chiffre le numéro de noyau 4.9.133. Ce sont les deux premiers chiffres qui comptent, le troisième n’est pas nécessairement le même que celui qui sera effectivement sélectionné pour compiler le système complet. Nouvelle valeur : 4.9.x
      • External toolchain C library : en tant que bibliothèque C, nous avons choisi de compiler une GlibC. Nouvelle valeur : glibc/eglibc
      • Toolchain has SSP support? : l’option Stack Smashing Protection (qui limite les dégâts en cas de débordement de buffer dans la pile) est active par défaut dans la GCC. Nouvelle valeur : [*].
      • Toolchain has RPC support? : le support pour les Remote Procedure Call est activé dans la chaîne de compilation produite. Nous pouvons l’ajouter ici. Nouvelle valeur : [*].
      • Toolchain has C++ support : l’intégration d’un compilateur C++ dans la toolchain était activée par défaut lors de la compilation précédente. Nouvelle valeur : [*]
  • System Configuration : rien à changer dans ce menu, mais nous l’ajusterons un peu plus tard.
  • Kernel : rien à changer
  • Target packages : rien à changer
  • Filesystem images : rien à changer
  • Bootloaders : rien à changer
  • Host utilities : rien à changer
  • Legacy config options : rien à changer

À nouveau, sauvegardons notre configuration pour pouvoir la réutiliser directement si besoin et lançons la compilation.

[buildroot-2015.11]$ cp .config ../board/rpi-3/buildroot-2018.02-system-01.config
[buildroot-2015.11]$ make

La compilation se termine au bout de quelques minutes avec en haut de la page de message une ligne plutôt surprenante :

/usr/bin/install -m 0644 support/misc/target-dir-warning.txt /home/testing/Build/br-tree/buildroot-2018.02.7/output/target/THIS_IS_NOT_YOUR_ROOT_FILESYSTEM
[...]
vfat(boot.vfat): adding file 'rpi-firmware/fixup.dat' as 'rpi-firmware/fixup.dat' ...
vfat(boot.vfat): adding file 'rpi-firmware/start.elf' as 'rpi-firmware/start.elf' ...
vfat(boot.vfat): adding file 'rpi-firmware/overlays' as 'rpi-firmware/overlays' ...
vfat(boot.vfat): adding file 'zImage' as 'zImage' ...
hdimage(sdcard.img): adding partition 'boot' (in MBR) from 'boot.vfat' ...
hdimage(sdcard.img): adding partition 'rootfs' (in MBR) from 'rootfs.ext4' ...
hdimage(sdcard.img): writing MBR
[buildroot-2018.02.7]

Mais que signifie donc ce THIS_IS_NOT_YOUR_ROOT_FILESYSTEM ?

Il s’agit en fait d’un nom de fichier, très anodin. Lorsque Buildroot prépare l’arborescence de la cible, il construit une représentation de son système de fichiers, qui se trouve dans output/target. Ces fichiers sont créés en appartenant à l’utilisateur courant. Or les fichiers systèmes (ceux se trouvant dans les répertoires /bin, /etc, /usr… de la cible) doivent appartenir à root. Pour pouvoir produire une image (une archive tar par exemple) avec les bonnes appartenances, on fait appel à un utilitaire nommé fakeroot qui modifie les droits au moment de la création de l’archive. Pas d’inquiétude, il n’y a rien de malicieux là-dessous, aucun problème de sécurité.

Comme le répertoire output/target contient des fichiers n’ayant pas la bonne appartenance, il ne faut pas l’utiliser aveuglément, ne pas le copier directement sur une cible où l’exporter pour un montage NFS root. C’est ce que Buildroot nous rappelle en créant ce fameux fichier :

[buildroot-2018.02.7]$ ls output/target/
bin  lib      media  proc  sbin                              tmp
dev  lib32    mnt    root  sys                               usr
etc  linuxrc  opt    run   THIS_IS_NOT_YOUR_ROOT_FILESYSTEM  var
[buildroot-2015.11]$

Installation et boot

Depuis quelques versions, l’installation de l’image sur un Raspberry Pi est devenue beaucoup plus simple puisqu’il suffit de copier un simple fichier sur l’ensemble de la carte micro-SD.

Avant de faire quoique ce soit, lancez la commande lsblk afin de voir la liste des périphériques blocs et partitions présents. En voici un exemple :

[buildroot-2018.02.7]$ lsblk
NAME           MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINT
sda              8:0    0 465,8G  0 disk  
├─sda1           8:1    0   400G  0 part  /home/testing
└─sda2           8:2    0     8G  0 part  [SWAP]
nvme0n1        259:0    0 232,9G  0 disk
├─nvme0n1p1    259:1    0   512M  0 part  /boot/efi
├─nvme0n1p2    259:2    0 224,6G  0 part  /
└─nvme0n1p3    259:3    0   7,8G  0 part
  └─cryptswap1 253:0    0   7,8G  0 crypt
[buildroot-2018.02.7]$

Insérons une carte micro-SD sur le poste de développement (par exemple avec un adaptateur USB), puis relançons la même commande pour voir ce qui est apparu.

[buildroot-2018.02.7]$ lsblk
NAME           MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINT
sda              8:0    0 465,8G  0 disk
├─sda1           8:1    0   400G  0 part  /home/testing
└─sda2           8:2    0     8G  0 part  [SWAP]
sdb              8:16   1  14,4G  0 disk
├─sdb1           8:17   1    32M  0 part  /media/cpb/86B1-7E7E
└─sdb2           8:18   1   400M  0 part  /media/cpb/68346014-8add-4d95-84f1-1dad224
nvme0n1        259:0    0 232,9G  0 disk
├─nvme0n1p1    259:1    0   512M  0 part  /boot/efi
├─nvme0n1p2    259:2    0 224,6G  0 part  /
└─nvme0n1p3    259:3    0   7,8G  0 part
  └─cryptswap1 253:0    0   7,8G  0 crypt
[buildroot-2018.02.7]$

Dans cet exemple, il s’agit du périphérique sdb, c’est ce que nous utiliserons ci-dessous.

Attention à ne pas vous tromper d’identifiant de périphérique ! cela pourrait être dangereux pour votre système si vous confondez avec votre disque dur par exemple.

Je démonte les partitions auto-montées de la carte micro-SD (sdb1 et sdb2 dans mon cas). Ceci est indispensable pour s’assurer qu’il n’y aura plus d’accès à ces emplacements de la carte.

[buildroot-2018.02.7]$ umount /dev/sdb?

Tous les éléments produits par Buildroot se trouvent dans son arborescence output/. Je m’intéresse à output/images/ qui contient les éléments à installer sur le système cible et plus particulièrement à output/images/sdcard.img qui représente le contenu complet de l’image à inscrire sur la carte SD.

Il est important de comprendre que ce fichier doit venir écraser l’ensemble des données de la carte SD, y compris les premiers secteurs contenant la table des partitions. Nous devons donc écrire sur le périphérique bloc lui-même /dev/sdb et pas dans le système de fichiers qu’il peut contenir.

[buildroot-2018.02.7]$ sudo cp output/images/sdcard.img /dev/sdb

La copie dure un petit moment, c’est normal, il faut remplir quelques centaines de méga-octets. Pas d’inquiétude sur la taille de la carte SD, Buildroot n’utilise que le minimum vital.

Une fois la copie terminée, j’insère la carte micro-SD sur un Raspberry Pi 3 auquel je suis relié par une liaison série avec un câble USB-Série de ce genre (lien Amazon : https://amzn.to/2AHKbaH).

J’observe les messages suivants à la mise sous tension.

[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 4.9.79-v7 (cpb@why-cpb) (gcc version 6.4.0 (Buildroot 2018.02.7) ) #1 SMP Sat Nov 3 08:18:16 CET 2018
[    0.000000] CPU: ARMv7 Processor [410fd034] revision 4 (ARMv7), cr=10c5383d
[    0.000000] CPU: div instructions available: patching division code
[    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
[    0.000000] OF: fdt:Machine model: Raspberry Pi 3 Model B Rev 1.2
[    0.000000] cma: Reserved 8 MiB at 0x39400000
[    0.000000] Memory policy: Data cache writealloc                                                             
[    0.000000] percpu: Embedded 14 pages/cpu @b8b91000 s25548 r8192 d23604 u57344                               
[    0.000000] Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 234465                      
[    0.000000] Kernel command line: 8250.nr_uarts=1 bcm2708_fb.fbwidth=720 bcm2708_fb.fbheight=480 bcm2708_fb.fbswap=1 vc_mem.mem_base=0x3ec00000 vc_mem.mem_size=0x40000000  root=/de
v/mmcblk0p2 rootwait console=tty1 console=ttyAMA0,115200                                                        
[    0.000000] PID hash table entries: 4096 (order: 2, 16384 bytes)
[    0.000000] Dentry cache hash table entries: 131072 (order: 7, 524288 bytes)
[    0.000000] Inode-cache hash table entries: 65536 (order: 6, 262144 bytes)
[    0.000000] Memory: 916004K/946176K available (7168K kernel code, 485K rwdata, 2012K rodata, 1024K init, 769K bss, 21980K reserved, 8192K cma-reserved)
[    0.000000] Virtual kernel memory layout:
[    0.000000]     vector  : 0xffff0000 - 0xffff1000   (   4 kB)
[    0.000000]     fixmap  : 0xffc00000 - 0xfff00000   (3072 kB)
[    0.000000]     vmalloc : 0xba000000 - 0xff800000   (1112 MB)
[    0.000000]     lowmem  : 0x80000000 - 0xb9c00000   ( 924 MB)
[    0.000000]     modules : 0x7f000000 - 0x80000000   (  16 MB)
[    0.000000]       .text : 0x80008000 - 0x80800000   (8160 kB)
[    0.000000]       .init : 0x80b00000 - 0x80c00000   (1024 kB)
[    0.000000]       .data : 0x80c00000 - 0x80c797ec   ( 486 kB)
[    0.000000]        .bss : 0x80c7b000 - 0x80d3b7d4   ( 770 kB)
[    0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=1
[    0.000000] Hierarchical RCU implementation.
[    0.000000]  Build-time adjustment of leaf fanout to 32.
[    0.000000] NR_IRQS:16 nr_irqs:16 16
[    0.000000] arm_arch_timer: Architected cp15 timer(s) running at 19.20MHz (phys).
[    0.000000] clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x46d987e47, max_idle_ns: 440795202767 ns
[    0.000006] sched_clock: 56 bits at 19MHz, resolution 52ns, wraps every 4398046511078ns
[    0.000022] Switching to timer-based delay loop, resolution 52ns
[    0.000288] Console: colour dummy device 80x30
[    0.001122] console [tty1] enabled
[    0.001169] Calibrating delay loop (skipped), value calculated using timer frequency.. 38.40 BogoMIPS (lpj=192000)
[    0.001235] pid_max: default: 32768 minimum: 301
[    0.001566] Mount-cache hash table entries: 2048 (order: 1, 8192 bytes)
[    0.001607] Mountpoint-cache hash table entries: 2048 (order: 1, 8192 bytes)
[    0.002630] Disabling memory control group subsystem
[    0.002731] CPU: Testing write buffer coherency: ok
[    0.002793] ftrace: allocating 22277 entries in 66 pages
[    0.050948] CPU0: update cpu_capacity 1024
[    0.050998] CPU0: thread -1, cpu 0, socket 0, mpidr 80000000
[    0.051059] Setting up static identity map for 0x100000 - 0x100034
[    0.052879] CPU1: update cpu_capacity 1024
[    0.052886] CPU1: thread -1, cpu 1, socket 0, mpidr 80000001
[    0.053516] CPU2: update cpu_capacity 1024
[    0.053523] CPU2: thread -1, cpu 2, socket 0, mpidr 80000002
[    0.054137] CPU3: update cpu_capacity 1024
[    0.054144] CPU3: thread -1, cpu 3, socket 0, mpidr 80000003
[    0.054228] Brought up 4 CPUs
[    0.054401] SMP: Total of 4 processors activated (153.60 BogoMIPS).
[    0.054430] CPU: All CPU(s) started in HYP mode.
[    0.054456] CPU: Virtualization extensions available.
[    0.055261] devtmpfs: initialized
[    0.066042] VFP support v0.3: implementor 41 architecture 3 part 40 variant 3 rev 4
[    0.066355] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[    0.066416] futex hash table entries: 1024 (order: 4, 65536 bytes)
[    0.066992] pinctrl core: initialized pinctrl subsystem
[    0.067917] NET: Registered protocol family 16
[    0.069940] DMA: preallocated 1024 KiB pool for atomic coherent allocations
[    0.078576] hw-breakpoint: found 5 (+1 reserved) breakpoint and 4 watchpoint registers.
[    0.078625] hw-breakpoint: maximum watchpoint size is 8 bytes.
[    0.078800] Serial: AMBA PL011 UART driver
[    0.080640] bcm2835-mbox 3f00b880.mailbox: mailbox enabled
[    0.081178] uart-pl011 3f201000.serial: could not find pctldev for node /soc/gpio@7e200000/uart0_pins, deferring probe
[    0.081525] irq: no irq domain found for /soc/aux@0x7e215000 !
[    0.151767] bcm2835-dma 3f007000.dma: DMA legacy API manager at ba00d000, dmachans=0x1
[    0.153600] SCSI subsystem initialized
[    0.153781] usbcore: registered new interface driver usbfs
[    0.153882] usbcore: registered new interface driver hub
[    0.153996] usbcore: registered new device driver usb
[    0.160765] raspberrypi-firmware soc:firmware: Attached to firmware from 2017-09-12 15:21
[    0.162013] clocksource: Switched to clocksource arch_sys_counter
[    0.208294] VFS: Disk quotas dquot_6.6.0
[    0.208404] VFS: Dquot-cache hash table entries: 1024 (order 0, 4096 bytes)
[    0.208625] FS-Cache: Loaded
[    0.208897] CacheFiles: Loaded
[    0.220915] NET: Registered protocol family 2
[    0.221805] TCP established hash table entries: 8192 (order: 3, 32768 bytes)
[    0.221944] TCP bind hash table entries: 8192 (order: 4, 65536 bytes)
[    0.222202] TCP: Hash tables configured (established 8192 bind 8192)
[    0.222320] UDP hash table entries: 512 (order: 2, 16384 bytes)
[    0.222388] UDP-Lite hash table entries: 512 (order: 2, 16384 bytes)
[    0.222616] NET: Registered protocol family 1
[    0.223044] RPC: Registered named UNIX socket transport module.
[    0.223076] RPC: Registered udp transport module.
[    0.223103] RPC: Registered tcp transport module.
[    0.223130] RPC: Registered tcp NFSv4.1 backchannel transport module.
[    0.223945] hw perfevents: enabled with armv7_cortex_a7 PMU driver, 7 counters available
[    0.226226] workingset: timestamp_bits=14 max_order=18 bucket_order=4
[    0.241938] FS-Cache: Netfs 'nfs' registered for caching
[    0.242945] NFS: Registering the id_resolver key type
[    0.242998] Key type id_resolver registered
[    0.243026] Key type id_legacy registered
[    0.245378] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 251)
[    0.245522] io scheduler noop registered
[    0.245552] io scheduler deadline registered
[    0.245851] io scheduler cfq registered (default)
[    0.251351] BCM2708FB: allocated DMA memory f9510000
[    0.251402] BCM2708FB: allocated DMA channel 0 @ ba00d000
[    0.261057] Console: switching to colour frame buffer device 90x30
[    0.268860] Serial: 8250/16550 driver, 1 ports, IRQ sharing enabled
[    0.273794] bcm2835-rng 3f104000.rng: hwrng registered
[    0.276205] vc-mem: phys_addr:0x00000000 mem_base=0x3ec00000 mem_size:0x40000000(1024 MiB)
[    0.281384] vc-sm: Videocore shared memory driver
[    0.298369] brd: module loaded
[    0.309375] loop: module loaded
[    0.311728] Loading iSCSI transport class v2.0-870.
[    0.314688] usbcore: registered new interface driver smsc95xx
[    0.317156] dwc_otg: version 3.00a 10-AUG-2012 (platform bus)
[    0.547616] Core Release: 2.80a
[    0.549961] Setting default values for core params
[    0.552324] Finished setting default values for core params
[    0.755025] Using Buffer DMA mode
[    0.757306] Periodic Transfer Interrupt Enhancement - disabled
[    0.759652] Multiprocessor Interrupt Enhancement - disabled
[    0.762061] OTG VER PARAM: 0, OTG VER FLAG: 0
[    0.764412] Dedicated Tx FIFOs mode
[    0.766998] WARN::dwc_otg_hcd_init:1032: FIQ DMA bounce buffers: virt = 0xb9504000 dma = 0xf9504000 len=9024
[    0.771814] FIQ FSM acceleration enabled for :
[    0.771814] Non-periodic Split Transactions
[    0.771814] Periodic Split Transactions
[    0.771814] High-Speed Isochronous Endpoints
[    0.771814] Interrupt/Control Split Transaction hack enabled
[    0.784099] WARN::hcd_init_fiq:459: FIQ on core 1 at 0x80592a54
[    0.786554] WARN::hcd_init_fiq:460: FIQ ASM at 0x80592db4 length 36
[    0.788930] WARN::hcd_init_fiq:486: MPHI regs_base at 0xba078000
[    0.791258] dwc_otg 3f980000.usb: DWC OTG Controller
[    0.793584] dwc_otg 3f980000.usb: new USB bus registered, assigned bus number 1
[    0.795944] dwc_otg 3f980000.usb: irq 62, io mem 0x00000000
[    0.798321] Init: Port Power? op_state=1
[    0.800631] Init: Power Port (0)
[    0.803093] usb usb1: New USB device found, idVendor=1d6b, idProduct=0002
[    0.805451] usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[    0.807798] usb usb1: Product: DWC OTG Controller
[    0.810121] usb usb1: Manufacturer: Linux 4.9.79-v7 dwc_otg_hcd
[    0.812479] usb usb1: SerialNumber: 3f980000.usb
[    0.815599] hub 1-0:1.0: USB hub found
[    0.817889] hub 1-0:1.0: 1 port detected
[    0.821017] usbcore: registered new interface driver usb-storage
[    0.823507] mousedev: PS/2 mouse device common for all mice
[    0.826695] bcm2835-wdt 3f100000.watchdog: Broadcom BCM2835 watchdog timer
[    0.829251] bcm2835-cpufreq: min=600000 max=1200000
[    0.831824] sdhci: Secure Digital Host Controller Interface driver
[    0.834077] sdhci: Copyright(c) Pierre Ossman
[    0.836569] sdhost-bcm2835 3f202000.sdhost: could not get clk, deferring probe
[    0.841075] mmc-bcm2835 3f300000.mmc: could not get clk, deferring probe
[    0.843585] sdhci-pltfm: SDHCI platform and OF driver helper
[    0.848605] ledtrig-cpu: registered to indicate activity on CPUs
[    0.851200] hidraw: raw HID events driver (C) Jiri Kosina
[    0.853865] usbcore: registered new interface driver usbhid
[    0.856320] usbhid: USB HID core driver
[    0.859498] vchiq: vchiq_init_state: slot_zero = 0xb9580000, is_master = 0
[    0.863318] [vc_sm_connected_init]: start
[    0.872078] [vc_sm_connected_init]: end - returning 0
[    0.874879] Initializing XFRM netlink socket
[    0.877353] NET: Registered protocol family 17
[    0.879868] Key type dns_resolver registered
[    0.882529] Registering SWP/SWPB emulation handler
[    0.885600] registered taskstats version 1
[    0.893181] uart-pl011 3f201000.serial: cts_event_workaround enabled
[    0.895688] 3f201000.serial: ttyAMA0 at MMIO 0x3f201000 (irq = 87, base_baud = 0) is a PL011 rev2
[    1.842544] console [ttyAMA0] enabled
[    1.851380] 3f215040.serial: ttyS0 at MMIO 0x0 (irq = 220, base_baud = 50000000) is a 16550
[    1.865602] sdhost: log_buf @ b9507000 (f9507000)
[    1.952041] mmc0: sdhost-bcm2835 loaded - DMA enabled (>1)
[    1.962323] mmc-bcm2835 3f300000.mmc: mmc_debug:0 mmc_debug2:0
[    1.970764] mmc-bcm2835 3f300000.mmc: DMA channel allocated
[    1.999575] Indeed it is in host mode hprt0 = 00021501
[    2.092140] of_cfs_init
[    2.094394] random: fast init done
[    2.102985] of_cfs_init: OK
[    2.108505] uart-pl011 3f201000.serial: no DMA platform data
[    2.109314] mmc0: host does not support reading read-only switch, assuming write-enable
[    2.111307] mmc0: new high speed SDHC card at address 0007
[    2.112173] mmcblk0: mmc0:0007 SD16G 14.4 GiB
[    2.114015] mmc1: queuing unknown CIS tuple 0x80 (2 bytes)
[    2.115580] mmc1: queuing unknown CIS tuple 0x80 (3 bytes)
[    2.117148] mmc1: queuing unknown CIS tuple 0x80 (3 bytes)
[    2.119952] mmc1: queuing unknown CIS tuple 0x80 (7 bytes)
[    2.150795]  mmcblk0: p1 p2
[    2.179804] EXT4-fs (mmcblk0p2): couldn't mount as ext3 due to feature incompatibilities
[    2.193546] EXT4-fs (mmcblk0p2): couldn't mount as ext2 due to feature incompatibilities
[    2.210593] mmc1: new high speed SDIO card at address 0001
[    2.218664] usb 1-1: new high-speed USB device number 2 using dwc_otg
[    2.228171] EXT4-fs (mmcblk0p2): mounted filesystem with ordered data mode. Opts: (null)
[    2.228226] Indeed it is in host mode hprt0 = 00001101
[    2.248801] VFS: Mounted root (ext4 filesystem) readonly on device 179:2.
[    2.259641] devtmpfs: mounted
[    2.289627] Freeing unused kernel memory: 1024K
[    2.421684] EXT4-fs (mmcblk0p2): re-mounted. Opts: data=ordered
[    2.452413] usb 1-1: New USB device found, idVendor=0424, idProduct=9514
[    2.462164] usb 1-1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[    2.473227] hub 1-1:1.0: USB hub found
Starting logging: [    2.480116] hub 1-1:1.0: 5 ports detected
OK
Initializing random number generator... done.
Starting network: Waiting for interface eth0 to appear[    2.802056] usb 1-1.1: new high-speed USB device number 3 using dwc_otg
[    2.932300] usb 1-1.1: New USB device found, idVendor=0424, idProduct=ec00
[    2.941753] usb 1-1.1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[    2.954518] smsc95xx v1.0.5
[    3.045558] smsc95xx 1-1.1:1.0 eth0: register 'smsc95xx' at usb-3f980000.usb-1.1, smsc95xx USB 2.0 Ethernet, b8:27:eb:fa:03:50
.
[    3.684451] smsc95xx 1-1.1:1.0 eth0: hardware isn't capable of remote wakeup
udhcpc: started, v1.27.2
udhcpc: sending discover
udhcpc: sending discover
udhcpc: sending discover
udhcpc: no lease, failing
FAIL

Welcome to Buildroot
buildroot login:

Il ne faut pas s’étonner, lorsqu’aucun câble n’est branché dans la prise Ethernet du Raspberry Pi, la fin du boot est un peu longue. Le service udhcpc répète ses sending discover toutes les trois secondes jusqu’à renoncer à joindre un serveur DHCP et affiche alors le message no lease, failing. Le script d’initialisation du réseau nous indique sèchement son échec d’un FAIL abrupt.

Nous disposons bien d’une invite de login, et pouvons nous connecter :

buildroot login: root
# uname -a
Linux buildroot 4.9.79-v7 #1 SMP Sat Nov 3 08:18:16 CET 2018 armv7l GNU/Linux

Le noyau correspondant bien à la version indiquée plus haut. Vérifions le processeur du Raspberry Pi 3.

# cat /proc/cpuinfo
processor       : 0
model name      : ARMv7 Processor rev 4 (v7l)
BogoMIPS        : 38.40
Features        : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32 
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x0
CPU part        : 0xd03
CPU revision    : 4

processor       : 1
model name      : ARMv7 Processor rev 4 (v7l)
BogoMIPS        : 38.40
Features        : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32 
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x0
CPU part        : 0xd03
CPU revision    : 4

processor       : 2
model name      : ARMv7 Processor rev 4 (v7l)
BogoMIPS        : 38.40
Features        : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32 
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x0
CPU part        : 0xd03
CPU revision    : 4

processor       : 3
model name      : ARMv7 Processor rev 4 (v7l)
BogoMIPS        : 38.40
Features        : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32 
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x0
CPU part        : 0xd03
CPU revision    : 4

Hardware        : BCM2835
Revision        : a02082
Serial          : 000000003efa0350
#

Nous avons bien observé les quatre cœurs de processeur du Raspberry Pi 3. Examinons l’état de la mémoire :

# free
             total       used       free     shared    buffers     cached
Mem:        925220      15908     909312         40        180       2192
-/+ buffers/cache:      13536     911684
Swap:            0          0          0

Le système compte au total un Go (dont une partie est réservée pour le contrôleur graphique) et dispose de 890 Mo de mémoire libre. En pressant deux fois la touche tabulation, nous pouvons voir la liste des commandes disponibles :

# (tab) (tab)
[                  fsck               mdev               sha3sum
[[                 fsfreeze           mesg               sha512sum
addgroup           fstrim             microcom           shred
adduser            fuser              mkdir              sleep
ar                 getopt             mkdosfs            sort
arp                getty              mke2fs             start-stop-daemon
arping             grep               mkfifo             strings
ash                gunzip             mknod              stty
awk                gzip               mkpasswd           su
basename           halt               mkswap             sulogin
blkid              hdparm             mktemp             svc
bunzip2            head               modprobe           swapoff
busybox            hexdump            more               swapon
bzcat              hostid             mount              switch_root
cat                hostname           mountpoint         sync
chattr             hwclock            mt                 sysctl
chgrp              i2cdetect          mv                 syslogd
chmod              i2cdump            nameif             tail
chown              i2cget             netstat            tar
chroot             i2cset             nice               tee
chrt               id                 nl                 telnet
chvt               ifconfig           nohup              test
cksum              ifdown             nproc              tftp
clear              ifup               nslookup           time
cmp                inetd              od                 top
cp                 init               openvt             touch
cpio               insmod             partprobe          tr
crond              install            passwd             traceroute
crontab            ip                 paste              true
cut                ipaddr             patch              truncate
date               ipcrm              pidof              tty
dc                 ipcs               ping               ubirename
dd                 iplink             pipe_progress      udhcpc
deallocvt          ipneigh            pivot_root         uevent
delgroup           iproute            poweroff           umount
deluser            iprule             printenv           uname
devmem             iptunnel           printf             uniq
df                 kill               ps                 unix2dos
diff               killall            pwd                unlink
dirname            killall5           rdate              unlzma
dmesg              klogd              readlink           unlzop
dnsd               last               readprofile        unxz
dnsdomainname      less               realpath           unzip
dos2unix           link               reboot             uptime
du                 linux32            renice             usleep
dumpkmap           linux64            reset              uudecode
echo               ln                 resize             uuencode
egrep              loadfont           rm                 vconfig
eject              loadkmap           rmdir              vi
env                logger             rmmod              vlock
ether-wake         login              route              w
expr               logname            run-parts          watch
factor             losetup            runlevel           watchdog
fallocate          ls                 sed                wc
false              lsattr             seq                wget
fbset              lsmod              setarch            which
fdflush            lsof               setconsole         who
fdformat           lspci              setkeycodes        whoami
fdisk              lsscsi             setlogcons         xargs
fgrep              lsusb              setpriv            xxd
find               lzcat              setserial          xz
flock              lzma               setsid             xzcat
fold               lzopcat            sh                 yes
free               makedevs           sha1sum            zcat
freeramdisk        md5sum             sha256sum
#

La commande ps nous affiche la liste des processus présents :

# ps
PID   USER     COMMAND
    1 root     init
    2 root     [kthreadd]
    3 root     [ksoftirqd/0]
    4 root     [kworker/0:0]
    5 root     [kworker/0:0H]
    6 root     [kworker/u8:0]
    7 root     [rcu_sched]
    8 root     [rcu_bh]
    9 root     [migration/0]
   10 root     [lru-add-drain]
   11 root     [cpuhp/0]
   12 root     [cpuhp/1]
   13 root     [migration/1]
   14 root     [ksoftirqd/1]
   15 root     [kworker/1:0]
   16 root     [kworker/1:0H]
   17 root     [cpuhp/2]
   18 root     [migration/2]
   19 root     [ksoftirqd/2]
   21 root     [kworker/2:0H]
   22 root     [cpuhp/3]
   23 root     [migration/3]
   24 root     [ksoftirqd/3]
   25 root     [kworker/3:0]
   26 root     [kworker/3:0H]
   27 root     [kdevtmpfs]
   28 root     [netns]
   29 root     [khungtaskd]
   30 root     [oom_reaper]
   31 root     [writeback]
   32 root     [kcompactd0]
   33 root     [crypto]
   34 root     [bioset]
   35 root     [kblockd]
   36 root     [watchdogd]
   37 root     [kworker/0:1]
   38 root     [rpciod]
   39 root     [xprtiod]
   40 root     [kswapd0]
   41 root     [vmstat]
   42 root     [nfsiod]
   52 root     [kthrotld]
   53 root     [bioset]
   54 root     [bioset]
   55 root     [bioset]
   56 root     [bioset]
   57 root     [bioset]
   58 root     [bioset]
   59 root     [bioset]
   60 root     [bioset]
   61 root     [bioset]
   62 root     [bioset]
   63 root     [bioset]
   64 root     [bioset]
   65 root     [bioset]
   66 root     [bioset]
   67 root     [bioset]
   68 root     [bioset]
   69 root     [bioset]
   70 root     [bioset]
   71 root     [bioset]
   72 root     [bioset]
   73 root     [bioset]
   74 root     [bioset]
   75 root     [bioset]
   76 root     [bioset]
   77 root     [iscsi_eh]
   78 root     [dwc_otg]
   79 root     [kworker/2:1]
   80 root     [DWC Notificatio]
   81 root     [VCHIQ-0]
   82 root     [VCHIQr-0]
   83 root     [VCHIQs-0]
   84 root     [VCHIQka-0]
   85 root     [SMIO]
   87 root     [kworker/2:2]
   88 root     [kworker/1:1]
   89 root     [kworker/3:2]
   90 root     [irq/92-mmc1]
   92 root     [bioset]
   93 root     [mmcqd/0]
   94 root     [kworker/0:1H]
   95 root     [jbd2/mmcblk0p2-]
   96 root     [ext4-rsv-conver]
  112 root     /sbin/syslogd -n
  115 root     /sbin/klogd -n
  117 root     [kworker/2:1H]
  152 root     [kworker/u8:1]
  154 root     -sh
  155 root     /sbin/getty -L tty1 0 vt100
  160 root     [kworker/2:0]
  161 root     ps
#

Hormis les threads du noyau (toutes les tâches avec des noms entre crochets), nous observons la présence de seulement six processus :

    • init : le premier processus qui est chargé d’abord de l’initialisation du système depuis l’espace utilisateur et par la suite de « l’adoption » des processus dont le parent se termine ;
    • syslogd et klogd : démons chargés de l’enregistrement des messages du système ;
    • getty : l’outil qui attend les connexions sur le terminal tty1 (écran HDMI + clavier USB), je suis connecté sur la console série et le getty correspondant a laissé sa place au shell ;
  • sh le shell sur lequel nous sommes connectés et la commande ps elle-même.

Voilà un système dont le contenu est bien sous contrôle !

Affinement de la configuration

Nous pouvons faire une première série d’améliorations, afin d’obtenir un système un peu plus convivial, accueillant un autre utilisateur que root par exemple ou renforçant la partition principale contre les risques de coupures d’alimentation intempestives.

Configuration de Buildroot

[buildroot-2018.02.7]$ make menuconfig
    • Menu System configuration :
        • System hostname: Choisissons un nom plus représentatif pour notre carte. Il apparaîtra par exemple dans l’invite de connexion, et nous l’afficherons également dans le prompt du shell. Nouvelle valeur : R-Pi.
        • System banner : Cette petite phrase s’affichera au démarrage avant la proposition de connexion ; on peut la personnaliser à volonté. Nouvelle valeur : Welcome on board!
        • Enable root login with password : Si le système a la moindre chance de se retrouver connecté à Internet, il est préférable de désactiver cette option. En effet le compte root sera le premier visé par les attaques automatiques par force brute. Si cette option est désactivée, il faudra intégrer la commande sudo afin de pouvoir réaliser les opérations d’administration. Sur un système expérimental, nous laissons la valeur originale : [*].
        • remount root filesystem read-write during boot : Sur un système embarqué où l’alimentation peut être coupée à tout moment, il est conseillé de conserver le système de fichiers principal en lecture-seule. On le basculera en lecture-écriture temporairement pour des modifications de configuration par exemple. Nouvelle valeur : [ ]
        • Network interface to configure through DHCP : Suivant la configuration, on utilisera ou non une configuration réseau par DHCP. Si tel est le cas, on indique ici le nom de l’interface Ethernet, laissant donc la valeur : eth0.
        • Path to the users tables : On indique ici le chemin d’accès pour un fichier contenant la liste des utilisateurs (voir plus loin). Nouvelle valeur : $(TOPDIR)/../board/rpi-3/users.tbl.
      • Root filesystem overlay directories : Le répertoire indiqué ici est l’origine d’une arborescence qui sera appliquée « par-dessus » le système de fichiers obtenu à l’issue des compilations et installations, avant de préparer l’image de sortie. Autrement dit notre arborescence va venir se superposer (remplaçant éventuellement des fichiers) à celle se trouvant dans output/target avant de la stocker dans output/image/rootfs.tar. Nous détaillerons plus loin ce qu’il faut ajouter dans cet overlay. Nouvelle valeur : $(TOPDIR)/../board/rpi-3/ovl.

Table des utilisateurs

Nous avons rempli l’option Path to the users tables avec le nom d’un fichier qui contient la liste des utilisateurs. Il doit y avoir un compte par ligne. Les champs, séparés par un espace, sont les suivants :

        • login : identifiant de connexion du compte (sauf root).
        • uid : numéro d’utilisateur. On peut indiquer -1 pour que l’attribution soit automatique, mais nous aurons besoin un peu plus loin d’une UID connue, je précise donc 1000.
        • group : groupe principal de l’utilisateur. Généralement le même nom que le login, ou alors un groupe global pour tous les comptes, comme users.
        • gid : numéro du groupe. Comme pour le champ uid, je précise 1000 pour connaître à l’avance le numéro de groupe.
        • password : le mot de passe, en clair si précédé d’un ‘=‘, crypté sinon. Si le mot de passe est ‘!‘, pas de connexion possible (compte utilisé pour un démon système par exemple).
        • home : répertoire personnel (aucun si ‘-‘).
        • shell : le shell de connexion. Sur notre système minimal, /bin/sh est un shell ash inclus dans Busybox.
        • groups : ce champ contient la liste des groupes supplémentaires auxquels appartient l’utilisateur (-1 si aucun).
      • gecos : des informations sur le compte, comme le nom en clair de l’utilisateur. Ce dernier champ peut contenir éventuellement des espaces.

Voici notre fichier ../board/rpi-3/users.tbl :

rpi 1000 rpi 1000 =rpi /home/rpi /bin/sh - Raspberry Pi User

Overlay

Comme indiqué plus haut nous nous créons une arborescence spécifique, contenant des fichiers qui viendront s’ajouter à ceux produits par Buildroot.

[buildroot-2018.02.7]$ mkdir -p ../board/rpi-3/ovl/usr/bin/

Scripts supplémentaires

Le système de fichiers principal est monté en lecture seule. Mais il est parfois nécessaire de repasser temporairement en lecture-écriture. Pour cela j’ai l’habitude de créer deux petits scripts rw et ro qui remontent la racine du système de fichiers respectivement en lecture-écriture ou lecture seule. Pour que Buildroot puisse les intégrer automatiquement dans l’image qu’il produit, nous les plaçons dans l’arborescence overlay :

[buildroot-2018.02.7]$ nano ../board/rpi-3/ovl/usr/bin/rw

Contenu du script rw

#! /bin/sh

mount / -o rw,remount
[buildroot-2018.02.7]$ cp ../board/rpi-3/ovl/usr/bin/rw ../board/rpi-3/ovl/usr/bin/ro
[buildroot-2018.02.7]$ nano ../board/rpi-3/ovl/usr/local/bin/ro

Contenu du script ro

#! /bin/sh

mount / -o ro,remount
[buildroot-2018.02.7]$ chmod +x ../board/rpi-3/ovl/usr/bin/*

Lançons la nouvelle compilation

[buildroot-2018.02.7]$ make

Nous ré-insérons la carte micro-SD dans le PC de développement et re-flashons l’image.

[buildroot-2018.02.7]$ umount /dev/sdb?
[buildroot-2018.02.7]$ sudo cp output/images/sdcard.img /dev/sdb

Après redémarrage du Raspberry Pi, vérifions la connexion avec l’identité root :

Welcome on board!
R-Pi login: root
Password: (root)
#

Vérifions tout de suite si le système de fichiers est bien monté en lecture seulement.

# ls /
bin         lib         media       root        tmp
dev         lib32       mnt         run         usr
etc         linuxrc     opt         sbin        var
home        lost+found  proc        sys
# echo hello > /test-file
-sh: can't create /test-file: Read-only file system

Très bien. Vérifions qu’il soit possible de passer temporairement en lecture-écriture.

# rw
[   86.847490] EXT4-fs (mmcblk0p2): re-mounted. Opts: data=ordered
# echo hello > /test-file
# ls /
bin         lib         media       root        test-file
dev         lib32       mnt         run         tmp
etc         linuxrc     opt         sbin        usr
home        lost+found  proc        sys         var
# ro
[  116.742951] EXT4-fs (mmcblk0p2): re-mounted. Opts: data=ordered
# rm /test-file
rm: remove '/test-file'? y
rm: can't remove '/test-file': Read-only file system
# exit

La protection du système est donc correcte. Vérifions l’accès en tant qu’utilisateur normal.

Welcome on board!
R-Pi login: rpi
Password: (rpi)
$ pwd
/home/rpi
$ ls
$ echo hello > my-file
-sh: can't create my-file: Read-only file system
$

Ici, un petit problème se pose. La partition « système » de notre Raspberry Pi est bien protégée contre les écritures, mais nous aimerions peut-être disposer de possibilités de stockage de données utilisateur. Pour cela il va falloir envisager l’ajout d’une partition supplémentaire montée en lecture-écriture

Nouvelles améliorations

Nous allons donc ajouter une nouvelle partition, formatée en vfat, afin de contenir les données utilisateur. Comme j’en ai parlé dans cet article, le format vfat est beaucoup plus simple que les traditionnels ext4 et consorts, mais il résiste bien à des coupures d’alimentations pendant une écriture.

Il faut indiquer la présence de cette partition dans le fichier /etc/fstab. Nous allons copier le fichier original produit par Buildroot dans notre overlay et lui ajouter une dernière ligne.

[buildroot-2018.02.7]$ mkdir  -p  ../board/rpi-3/ovl/etc
[buildroot-2018.02.7]$ cp output/target/etc/fstab ../board/rpi-3/ovl/etc/
[buildroot-2018.02.7]$ nano ../board/rpi-3/ovl/etc/fstab

Le fichier est modifié ainsi (dernière ligne ajoutée)

/dev/root       /               ext2    rw,noauto       0       1
proc            /proc           proc    defaults        0       0
devpts          /dev/pts        devpts  defaults,gid=5,mode=620 0       0
tmpfs           /dev/shm        tmpfs   mode=0777       0       0
tmpfs           /tmp            tmpfs   mode=1777       0       0
tmpfs           /run            tmpfs   mode=0755,nosuid,nodev  0       0
sysfs           /sys            sysfs   defaults        0       0
/dev/mmcblk0p3  /home       vfat    defaults,uid=1000,gid=1000  0 0

Pour créer les partitions et l’image sdcard.img finale, Buildroot appelle le script board/raspberrypi3/post-image.sh (indiqué dans l’option « Custom scripts to run after creating filesystem images » du menu « System configuration« ). Ce script fait appel à un utilitaire nommé genimage en lui passant le fichier de configuration board/raspberrypi3/genimage-raspberrypi3.cfg.

Pour éviter de modifier un fichier fourni par Buildroot, nous pourrions copier le script et le fichier de configuration dans notre répertoire, les modifier à cet endroit, et fournir notre version dans l’option « Custom scripts to run after creating filesystem images« . Pour garder cet article relativement simple, je vais modifier directement le fichier de configuration genimage-raspberrypi3.cfg.

[buildroot-2018.02.7]$ nano board/raspberrypi3/genimage-raspberrypi3.cfg

Le fichier est modifié (lignes ajoutées en gras) pour devenir :

image boot.vfat {
  vfat {
    files = {
      "bcm2710-rpi-3-b.dtb",
      "bcm2710-rpi-cm3.dtb",
      "rpi-firmware/bootcode.bin",
      "rpi-firmware/cmdline.txt",
      "rpi-firmware/config.txt",
      "rpi-firmware/fixup.dat",
      "rpi-firmware/start.elf",
      "rpi-firmware/overlays",
      "zImage"
    }
  }
  size = 32M
}

image home.vfat {
  name = "home.vfat"
  vfat { 
    files = { }
  }
  size = 128M
  mountpoint = "/home"
}

image sdcard.img {
  hdimage {
  }

  partition boot {
    partition-type = 0xC
    bootable = "true"
    image = "boot.vfat"
  }

  partition rootfs {
    partition-type = 0x83
    image = "rootfs.ext4"
  }

  partition home {
    partition-type = 0xC
    image  = "home.vfat"
  }
}

Recompilons notre système, et réinscrivons-le sur la carte SD.

[buildroot-2018.02.7]$ make
[buildroot-2018.02.7]$ umount /dev/sdb?
[buildroot-2018.02.7]$ sudo cp output/images/sdcard.img /dev/sdb

Après démarrage du Raspberry Pi, nous pouvons vérifier que l’utilisateur rpi a bien accès à son répertoire personnel en lecture et écriture.

Welcome on board!
R-Pi login: rpi
Password: (rpi)
$ echo 1 > my-file
$ ls -l
total 2
-rwxr-xr-x    1 rpi      rpi              2 Jan  1 00:00 my-file
$ exit

Vérifions aussi que la partition système est bien en lecture seulement, même pour l’utilisateur root.

Welcome on board!
R-Pi login: root
Password: (root)
# echo 1 > my-file
-sh: can't create my-file: Read-only file system
#

Bien entendu, root peut appeler notre commande rw s’il souhaite vraiment modifier un fichier de l’arborescence système.

Conclusion

Nous disposons ainsi d’un système Linux embarqué minimal assez personnalisé. Bien sûr il faudra ajouter de nombreux outils pour avoir un véritable environnement de travail complet, citons par exemple le serveur SSH Dropbear, un serveur web comme celui de Busybox ou Lighttp, un client NTP, etc. Nous verrons cela dans de prochains articles.

62 Réponses

  1. wcdr dit :

    Un grand merci, enfin un article clair qui fonctionne.

    Je souhaiterai faire une chaine de compilation croisée pour le RPI 1, quelles sont les modifications à apporter dans la section « Toolchain – Voici la liste des modifications apportées : »

    Merci,

    Wz

    • cpb dit :

      Bonjour et merci,

      Pour la toolchain comme pour le reste du système, la seule différence entre Raspberry Pi 1 et 2 sera le make raspberrypi_defconfig au lieu de make raspberrypi2_defconfig.

      Toutefois si vous souhaitez disposer des deux toolchains sur la même machine, (afin de les utiliser successivement pour les deux types de Raspberry par exemple), je vous conseille de vous créer des répertoires distincts board/raspberrypi et board/raspberrypi2 en ajustant les chemins des paramètres Host dir puis Toolchain path et enfin dans la dernière partie Overlay directory.

  2. ibd dit :

    Excellent post. Bravo et merci.

  3. Laurent dit :

    Bonjour,

    Merci pour ce tuto très intéressant !

    J’ai relevé une coquille (en faisant un bête copié-collé)

    Pour le menu « Build options » –> « Host dir » vous le valorisez à
    ($TOPDIR)/../board/raspberrypi2/cross/

    au lieu de
    $(TOPDIR)/../board/raspberrypi2/cross
    ($ pas à la bonne place et / de trop en fin )

    Merci !

  4. Christophe dit :

    Bonjour Christophe,
    Merci beaucoup pour vos tuto toujours très instructif.

    Je suis confronté à un problème:
    si je cherche à créer une chaîne de cross compilation sans changer le Host dir

  5. Christophe dit :

    Bonjour Christophe,

    Merci encore pour vos tutos très instructifs.

    Je suis confronté à un problème lors de la création de la chaîne de cross compilation:
    si je ne change pas le Host dir tout vat bien,
    mais si je fait la modification $(TOPDIR)/../board/raspberrypi2/cross
    j’obtiens l’erreur suivante:
    xargs: /home/radio/br-tree/buildroot-2015.11/../board/raspberrypi2/cross/usr/bin/arm-buildroot-linux-gnueabihf-strip: Aucun fichier ou dossier de ce type
    make[1]: *** [target-finalize] Erreur 127

    il semblerais que la variable $(TOPDIR) soit mal interprété, j’ai essayé de mettre un chemin complet même résultat, je ne vois pas ou se situe l’erreur.

    Le newbie que je suis est peut-être destiné à rester newbie?

    Cordialement.

    • Christophe dit :

      Re bonjour,

      Pour faire suite à mon post précédent, j’ai compris mon erreur elle est instructive.
      Au premier test de compilation j’ai fait une erreur dans l’écriture du paramètre Host dir à la suite de quoi
      Buildroot créé une chaîne de compilation mais pas au bon endroit et supprime des fichiers qui sont utiles
      par la suite.
      Pour contourner ce problème j’ai fait un effacement du répertoire buildroot et je recrée tout , ça fonctionne.

      le newbie est en progression!

      Cordialement

  6. Julien ROBIN dit :

    Bonjour

    Merci encore pour ces mines d’or d’informations,

    Me voilà entrain d’utiliser la même version de buildroot pour peu à peu m’attaquer, pour changer… à un Orange Pi 2 ! Il parait que c’est un challenge, mais je suis du genre à ne pas me dégonfler trop vite 🙂

    J’en reviens pour le moment aux bases : les datasheets des composants qui l’équipent, le site officiel ARM, big endian ou little endian, type de FPU utilisée…
    http://infocenter.arm.com/help/index.jsp

    Bref je commence à regarder tout ça, si j’arrive à quelque chose d’intéressant je vous tiens au jus !

  7. Mathieu dit :

    Bonjour et merci pour cet article très instructif.
    Une question me vient à l’esprit : quelle est la taille occupée par le système sur la carte sd ?

    • cpb dit :

      En regardant le répertoire output/images d’un Buildroot configuré globalement comme celui de l’article je vois :

      [images]$ ls -l
      total 53404
      -rw-r--r-- 1 cpb cpb    10180 janv.  8 01:39 bcm2709-rpi-2-b.dtb
      -rw-r--r-- 1 cpb cpb 46274560 janv.  8 01:49 rootfs.tar
      drwxr-xr-x 2 cpb cpb     4096 janv.  7 23:29 rpi-firmware
      -rw-r--r-- 1 cpb cpb   303560 janv.  8 01:22 u-boot.bin
      -rwxr-xr-x 1 cpb cpb  4040120 janv.  7 23:48 zImage
      [images]$ ls -l rpi-firmware/
      total 2684
      -rw-r--r-- 1 cpb cpb   17900 janv.  7 23:29 bootcode.bin
      -rw-r--r-- 1 cpb cpb      29 janv.  7 23:29 cmdline.txt
      -rw-r--r-- 1 cpb cpb     682 janv.  7 23:29 config.txt
      -rw-r--r-- 1 cpb cpb    6331 janv.  7 23:29 fixup.dat
      -rw-r--r-- 1 cpb cpb 2709752 janv.  7 23:29 start.elf
      [images]$ 

      Donc environ 7Mo sur la partition BOOT et 47Mo sur la partition ROOT. C’est un système plutôt léger !

  8. Richard Starzak dit :

    Bonjour,

    Merci pour ce tuto très intéressant.

    Mais, j’ai un problème.

    J’arrive à générer l’image, le boot (sur la RASPBERRY) démarre puis cale … : je ne vois vraiement pas que faire ?

    Voici la dernière ligne de la séquence de boot (après bien d’autres lignes) :

    —[ end Kernel panic – not syncing : VFS : Unable to mount root fs on unknown-block (0,0)

    Que puis-je faire ?

    Merci pour tout aide,

    Richard

  9. Claude dit :

    Bonjour,

    Encore merci pour la qualité de votre production. C’est rare.

    Dans le cadre du développement d’un GPS centimétrique (DGPS), j’ai pour projet d’installer l’application RTKLIB 2.4.2 (C++) sur RASPBERRY 3 tournant sous DEBIAN.

    En conséquence, je souhaiterai faire une chaine de compilation croisée pour le RPI 3, quelles sont les modifications à apporter?

    Merci pour votre aide.

    Claude

    • cpb dit :

      Bonjour Claude,

      Pour faire le même travail sur un Raspberry Pi 3, il suffit de prendre une version récente de Buildroot, par exemple la version 2016.05 ou 2016.08 qui est en finalisation, et de commencer par un make rasberrypi3_defconfig au lieu de make raspberrypi2_defconfig.

  10. Benoît dit :

    Bonjour,

    Merci pour vos articles !

    J’ai une question. Mettre le rootfs en lecture semble poser problème à ssh. Il me semble que ce dernier génère des clés lors de la première démarrage.

    Avez-vous une solution ? (je n »utilise pas raspberrypi, c’est une carte que je n’accède que par ssh). Merci.

    • cpb dit :

      Bonjour,

      C’est en effet un problème courant. On peut le résoudre de plusieurs manières.

      Si l’utilisation de SSH est très rare, le plus simple consiste à recréer de nouvelles clés à chaque fois, en demandant à sshd de les stocker sur une partition temporaire en lecture-écriture. L’inconvénient est l’impossibilité dans ce cas de faire des connexions automatiques (avec ssh-copy-id).

      Une autre possibilité consiste à modifier le script de démarrage de sshd, pour qu’il vérifier si les clés sont déjà définies. Si ce n’est pas le cas, il peut monter temporairement la partition root en lecture-écriture et la remettre en lecture-seule après enregistrement des clés. Si on craint une coupure d’alimentation pendant la génération des clés – étape qui prend plusieurs secondes – on peut faire un enregistrement temporaire sur une partition en lecture-écriture puis une copie sur la partition root. Attention dans ce cas à bien respecter les droits d’accès (lecture seulement pour root).

      Il y a sûrement d’autres possibilités, c’est un domaine où l’on peut être imaginatif !

  11. hsan dit :

    Bonsoir Monsieur ,
    Je veux installer un noyau linux Xenomai sur raspberrypi2.
    j’ai fais les étapes de « Création d’un système complet avec Buildroot 2015.11 » mais j’ai trouvé cet erreur :
    http://snapshot.debian.org/archive/debian/20141023T043132Z/pool/main/d/dsh/dash_0.5.8.orig.tar.gz
    ERREUR 404 not found

    pour impleementer Xenomai sur raspberry est ce que necessaire d’installer buildroot?

    • cpb dit :

      Bonjour.
      Cette version de Buildroot date de plus d’un an. Certains liens ont peut-être disparu, je vous conseille d’essayer avec une version plus récente de Buildroot.

  12. hsan dit :

    Bonsoir Monsieur,
    voila mon dernier erreur.Pouvez vous m’aidez?
    recipe for target ‘ /home/pi/br-tree/buildroot-2015.08.1/output/build/glibc-2.20/.stamp_configured’ failed

  13. hsan dit :

    Bonjour
    j’ai essayer plusieurs fois et la problème est la meme /.stamp_built’ failed Error 2
    pouvez vous m’aidez?

    • cpb dit :

      Bonjour,

      Durant quelle compilation de Buildroot le problème se pose-t-il, la première (toolchain) ou la seconde (système) ?

      La cible .stamp_built correspond à l’étape de compilation d’un package par Buildroot.
      La compilation d’un package a donc échoué. Quel package ? Quelle est la cause de l’erreur ?
      Sans plus de précision, je ne peux pas vous aider plus.

      Au passage, notez que l’erreur de vendredi soir était pour la cible « …/glibc-2.20/.stamp_configured » qui correspondait à un échec de configuration du package Glibc.

      Je vous conseille de vous placer à la racine de Buildroot, puis de refaire

      • make clean
      • make
  14. Damien G dit :

    Bonjour,
    Je me joins à tous les messages précédents pour vous féliciter pour la qualité et l’exhaustivité de cet article.
    Je suis parvenu à compléter la première étape (toolchain) en suivant scrupuleusement la démarche décrite.
    Puisque j’aimerais le support des en-tête du noyau en version 4.4.x et qu’il n’est pas présent dans buildroot 2015.11, j’ai tenté cette procédure avec la version suivante de buildroot (2016.02) qui manifestement donne accès à la version qui m’intéresse. Malheureusement, je rencontre le même problème que Hsan :

    tmp-divrem_1.s: Messages de l’assembleur:
    tmp-divrem_1.s:129: Erreur: le processeur choisi ne supporte pas le mode ARM « mls r1,r4,r8,r11 »
    … plusieurs fois

    make[1]: Leaving directory ‘/mnt/nasHomes/nei/dev/pi/linux/buildroot/br-tree2016_02/buildroot-2016.02/output/build/host-gmp-6.1.0’
    package/pkg-generic.mk:195: recipe for target ‘/mnt/nasHomes/nei/dev/pi/linux/buildroot/br-tree2016_02/buildroot-2016.02/output/build/host-gmp-6.1.0/.stamp_built’ failed
    Je n’ai pas trouvé de différence flagrante entre les deux versions et me voila bloqué….
    Avez-vous des idées ?
    DamienG

    • Damien G dit :

      Bonjour,
      Une petite précision qui a peut être son importance : je compile depuis un raspberry PI 2 …
      Damien G

    • cpb dit :

      Bonjour,
      C’est bizarre, vous avez initialisé la compilation comment ? « make raspberrypi2_defconfig » ?

      • Damien G dit :

        Bonsoir,

        Oui, comme précisé dans l’article. Avez-vous eu l’occasion de le faire avec les nouvelles versions de buildroot ?
        DamienG

      • DamienG dit :

        Bonjour,
        Pour information, j’ai aussi tenté de faire, à partir de mon RPi:
        make raspberrypi2_defconfig
        make
        avec le même résultat.

        Ne trouvant rien sur le sujet sur internet, j’ai tenté la même chose que ci-dessus mais depuis un PC Ubuntu, et là c’est allé au bout. Donc je suppose qu’il y a un problème avec la chaine de compilation du RPi.
        Je ne vais pas pousser plus loin et je vais continuer de compiler sur ma machine Ubuntu (d’autant que ça va sensiblement plus vite, même si elle date de 2007…)
        DamienG

  15. Sylvain POURRE dit :

    Bonjour M. Blaess

    tout d’abord, un grand merci pour ce site est ses nombreux articles.

    J’ai donc testé Buildroot, dans sa conf par défaut, et obtenu rapidement une image bootable.
    J’ai ensuite suivi votre conseil de compiler la toolchain indépendamment et de la réutiliser pour compiler une image et cela a fonctionné.

    Comme j’envisage, in fine, d’utiliser l’IDE Eclipse pour développer mes applis « métier », j’ai voulu intégrer le support du plugin. La création de l’image a échoué et une recherche sur google avec le mesage d’erreur m’a conduit à constater que ce fait est connu depuis août:

    http://lists.busybox.net/pipermail/buildroot/2017-August/199790.html

    Comme j’utilise la version du GIT, je pensais le patch intégré. J’ai aussi vu qu’il était recommandé d’utiliser un chemin absolu mais je n’ai pas encore tenté le lien symbolique suggéré dans l’échange pointé par mon lien.

    Pour le moment, seule une compil « globale », avec le chemin par défaut, me permet d’obtenir une image supportant GDB. Je ne l’ai pas encore testée car les binaires de la cible sont strippés.

    Avez-vous aussi rencontré ce problème où je passe à côté d’une option ? D’avance merci.
    Cordialement

    Sylvain

    • cpb dit :

      Je dois avouer que je n’ai jamais réussi à utiliser le plugin Eclipse, et que je fais la configuration d’Éclipse manuellement (ce qui n’est pas très intuitif pour le GDB distant).

      • Sylvain POURRE dit :

        Merci pour cette réponse très rapide.
        Me voilà rassuré . Je vais donc poursuivre sur la voie de ne pas déplacer la toolchain dans un premier temps.
        Comme il y a un bug ouvert, il sera peut-être corrigé.

  16. Dat Le dit :

    ¨ Après quelques minutes, la compilation se termine avec ces lignes …¨
    Sur quelle machine svp!.
    Sur une Raspiberry pi 3, il me prend au mois 3 heures, et la compilation crashed au
    denier moment.
    Merci beaucoup.

    • cpb dit :

      En général on utilise Buildroot sur un PC, pour préparer une image pour un système embarqué, pas sur la cible elle-même…
      Il n’y a pas de raison toutefois que ça échoue sur une Raspberry Pi 3, mais il faut utiliser une version actuelle de Buildroot : la version long terme 2017.02.7 ou 2017.08.1.

  17. Mathieu dit :

    Bonjour Christophe,

    Merci tout d’abord pour ce tuto 🙂

    Je suis débutant et je me retrouve face à une erreur bloquante lorsque je lance la première compilation :

    The directory that should contain system headers does not exist:
    board/raspberrypi/cross/arm-buildroot-linux-gnueabihf/sysroot/usr/include
    Makefile:2909 : la recette pour la cible « stmp-fixinc » a échouée
    make[3]: *** [stmp-fixinc] Erreur 1
    make[3] : on quitte le répertoire « /home/mathieu/br-tree/buildroot-2017.11/output/build/host-gcc-final-6.4.0/build/gcc »
    Makefile:4133 : la recette pour la cible « all-gcc » a échouée
    make[2]: *** [all-gcc] Erreur 2
    make[2] : on quitte le répertoire « /home/mathieu/br-tree/buildroot-2017.11/output/build/host-gcc-final-6.4.0/build »
    Makefile:877 : la recette pour la cible « all » a échouée
    make[1]: *** [all] Erreur 2
    make[1] : on quitte le répertoire « /home/mathieu/br-tree/buildroot-2017.11/output/build/host-gcc-final-6.4.0/build »
    package/pkg-generic.mk:234 : la recette pour la cible « /home/mathieu/br-tree/buildroot-2017.11/output/build/host-gcc-final-6.4.0/.stamp_built » a échouée
    make: *** [/home/mathieu/br-tree/buildroot-2017.11/output/build/host-gcc-final-6.4.0/.stamp_built] Erreur 2

    J’ai essayé de créer le dossier « cross » dans /board/raspberrypi mais j’ai toujours l’erreur

    Voici le contenu de mon host dir : $(TOPDIR)/../board/raspberrypi/cross

    Merci d’avance pour le coup de main

    Mathieu

    • cpb dit :

      Bonjour,
      Le dossier board/raspberrypi/ doit être créé manuellement « à côté » du répertoire de Buildroot.
      Ainsi :

      $ mkdir -p  board/raspberrypi
      $ wget http://www.buildroot...
      $ tar xf buildroot...
      • Mathieu dit :

        Bonjour,

        Merci pour votre réponse.

        C’est exactement ce que j’ai fait.

        Voici le « ls » de mon fichier br-tree : board buildroot-2017.11 buildroot-2017.11.tar.bz2 dl

        Et dans board j’ai bien crée le dossier « raspberrypi » (il y a également le fichier de config)

        Cordialement,

        Mathieu

      • Mathieu dit :

        En fait, l’erreur venait d’une bête erreur de saisie de ma part, bien entendu… 🙂

        J’ai effectué ensuite la compilation du système complet et je bloque désormais au message d’erreur suivant :

        Allocation des tables de groupe : complété
        Écriture des tables d’i-noeuds : complété
        Création du journal (4096 blocs) : complété
        Copie des fichiers dans le périphérique : __populate_fs: N’a pu allouer de bloc dans le système de fichiers ext2 lors de l’écriture du fichier « libstdc++.so.6.0.22 »
        mkfs.ext4: N’a pu allouer de bloc dans le système de fichiers ext2 lors du peuplement du système de fichier
        *** Maybe you need to increase the filesystem size (BR2_TARGET_ROOTFS_EXT2_SIZE)
        fs/ext2/ext2.mk:48 : la recette pour la cible « /home/mathieu/br-tree/buildroot-2017.11/output/images/rootfs.ext2 » a échouée
        make: *** [/home/mathieu/br-tree/buildroot-2017.11/output/images/rootfs.ext2] Erreur 1

        Auriez vous une idée de quoi cela eut il venir ?

        Merci d’avance !

        • cpb dit :

          Bonjour,

          L’erreur indique que le système de fichiers prévu est trop petit. Buildroot n’arrive pas à y inscrire la bibliothèque C++.
          C’est surprenant, je ne me souviens pas avoir rencontré cela.
          Pour corriger le problème, il faut aller dans le menu « Filesystem images » de Buildroot, et remplir le champ « exact size in blocks » avec une valeur assez grande. Par exemple 2097152 qui dimensionnera le système de fichiers à 1Go (il me semble que les blocs font 512 octets).

  18. Mathieu dit :

    Effectivement, ça fonctionne maintenant.

    Un grand merci 🙂

    • cpb dit :

      Le hasard est amusant, je viens juste d’obtenir la même erreur (pour la première fois). Il y a peut-être une erreur de calcul dans la dernière version de Buildroot. Au passage, on peut préciser directement la taille du système de fichier, par exemple « 512M » pour 512 Mo, inutile de faire le calcul en blocs.

      • Mathieu dit :

        Ah… effectivement :D.

        Oui peut être une erreur de calcul.

        Effectivement , c’est ce que j’ai vu. J’ai remplacé la valeur de base « 60M » par « 512M » et ça fonctionne.

        • Mathieu dit :

          Bonjour Monsieur Blaess,

          En faisant une nouvelle compilation pour la raspberry 0 (raspberry0_defconfig) j’ai le message d’erreur suivant cette fois -ci (cf ci-dessous)

          Je n’arrive pas à trouver de l’aide à ce sujet auriez vous une idée ?

          Merci d’avance !

          /usr/bin/install -m 0644 support/misc/target-dir-warning.txt /home/mathieu/br-tree/buildroot-2017.11/output/target/THIS_IS_NOT_YOUR_ROOT_FILESYSTEM
          ln -sf rootfs.ext2 /home/mathieu/br-tree/buildroot-2017.11/output/images/rootfs.ext4
          >>> Executing post-image script board/raspberrypi0/post-image.sh
          file(bcm2708-rpi-b-plus.dtb): stat(/home/mathieu/br-tree/buildroot-2017.11/output/images/bcm2708-rpi-b-plus.dtb) failed: No such file or directory
          vfat(boot.vfat): could not setup bcm2708-rpi-b-plus.dtb
          Makefile:745 : la recette pour la cible « target-post-image » a échouée
          make: *** [target-post-image] Erreur 1

  19. Mathieu dit :

    Bonjour Monsieur Blaess,

    En faisant une nouvelle compilation pour la raspberry 0 (raspberry0_defconfig) j’ai le message d’erreur suivant cette fois -ci (cf ci-dessous)

    Je n’arrive pas à trouver de l’aide à ce sujet auriez vous une idée ?

    Merci d’avance !

    /usr/bin/install -m 0644 support/misc/target-dir-warning.txt /home/mathieu/br-tree/buildroot-2017.11/output/target/THIS_IS_NOT_YOUR_ROOT_FILESYSTEM
    ln -sf rootfs.ext2 /home/mathieu/br-tree/buildroot-2017.11/output/images/rootfs.ext4
    >>> Executing post-image script board/raspberrypi0/post-image.sh
    file(bcm2708-rpi-b-plus.dtb): stat(/home/mathieu/br-tree/buildroot-2017.11/output/images/bcm2708-rpi-b-plus.dtb) failed: No such file or directory
    vfat(boot.vfat): could not setup bcm2708-rpi-b-plus.dtb
    Makefile:745 : la recette pour la cible « target-post-image » a échouée
    make: *** [target-post-image] Erreur 1

    • cpb dit :

      Entre deux builds avec deux cibles différentes raspberrypi_2 et raspberrypi_0 par exemple, il est important d’effacer tous les produits de compilation (fichiers objets, temporaires, etc.)
      Un « make clean » peut suffire, mais il est souvent plus simple d’effacer tout le répertoire de Buildroot et de le ré-extraire à nouveau.

      • Mathieu dit :

        Merci pour votre retour mais rien n’y fait même après avoir effacé et ré-extrait tout le répertoire de buildroot, toujours le même soucis… Je creuse mais pas grand chose sur les forums malheureusement

  20. Mathieu dit :

    Bonjour Christophe,

    Apparemment le package mkknlimg n’existe plus dans la nouvelle version de buildroot.

    Par quelle commande faut il donc remplacer la commande :

    sudo ./output/host/usr/bin/mkknlimg output/images/zImage /media/xxxx/BOOT/zImage

    D’avance merci.

    Bien à vous,

    Mathieu

  21. Sylvain dit :

    Cet article est bien indexé lorsque l’on s’interroge sur buildroot et raspberry, du coup il pourrait être utile de le mettre à jour car il me semble que la fin peut être simplifié grâce à, j’imagine, des évolution des buildroot depuis la publication initiale de cet article.

    Buildroot génère en effet un fichier sdcard.img qui peut être écrit directement sur la carte en s’affranchissant de la définition des partitions évoquées dans cet article. C’est sûrement moins précis mais ça permet de faire de premiers tests assez facilement.

    • cpb dit :

      En effet, une mise à jour de l’article serait intéressante étant donné qu’il « sort » facilement des moteurs de recherche.
      Je vais m’en occuper prochainement. L’installation est effectivement beaucoup plus simple de nos jours avec le fichier sdcard.img.
      Merci.

      • Sylvain dit :

        Merci pour la réponse, et je profite donc de voir que vous lisez les commentaires pour vous faire part d’un problème que je viens de rencontrer en tentant d’adapter la procédure à la config raspberrypi plutôt que le 2. Mon make initial finit avec les lignes suivantes :

        file(bcm2708-rpi-b.dtb): stat(/home/nous/br/br-tree/buildroot-2018.02.6/output/images/bcm2708-rpi-b.dtb) failed: No such file or directory
        vfat(boot.vfat): could not setup bcm2708-rpi-b.dtb
        Makefile:768: recipe for target ‘target-post-image’ failed
        make: *** [target-post-image] Error 1

        Si vous avez une idée je suis preneur !

        S.

        • tqhien dit :

          Bonjour,

          J’ai aussi eu ce genre de message. Il suffit de copier/coller à la main le(s) fichier(s) en erreur (ici bcm2708-rpi_b.dtb dans le répertoire output/images. On trouve ces fichiers sur le github du rpi : https://github.com/raspberrypi/firmware/tree/master/boot

          Il faut aussi créer le fichier zImage pendant la 1ère phase, même si les outils ont déjà été créés (un « touch zImage » dans le même répertoire suffit).

          Enfin, j’ai eu des erreurs sur des versions de kernel « too old », avec les fichiers de configuration par défaut pour la création du système complet (Je n’ai pas compris pourquoi il me compilait un noyau 4.15 (celle de mon ordi) alors que la config de buildroot demande une 4.9 par exemple…) Il a fallu que j’aille chercher le numéro du dernier commit de la branche 4.15 sur le github linux de raspberry (https://github.com/raspberrypi/linux). Par exemple, au 31/10/2018, pour la branche rpi-4.15.y, c’est le commit du 20 mai numéroté 1b75d3e7314049bbf1222d447e1c44928e9a478b que j’ai mis dans ma config de buildroot (menu kernel/custom de mémoire, juste en dessous d’un champ avec une adresse github dedans)

        • cpb dit :

          Ce genre d’erreur se produit souvent lorsqu’on commence à préparer un système, puis qu’on modifie les infos les pour la toolchain et qu’on essaye de recompiler alors qu’il y a des fichiers déjà produits. Une solution est bien souvent un « make clean; make » (qui prend du temps).

          NB: La mise à jour de l’article est bien sur ma tasklist mais le temps disponible est rare…

  22. Thibault dit :

    Article génial, rien à ajouter. Bravo !

  23. vervein dit :

    Bonjour Christophe,
    j’ai une erreur quand j’essaye de compiler une image système d’après vos instructions:

    External toolchain uses the unsuported OABI
    make: *** [package/pkg-generic.mk:216: ../buildroot-2018.02.7/output/build/toolchain-external-custom/.stamp_configured] Error 1

    en faisant quelques recherches, j’ai trouvé ça:
    « Old Linux kernel on ARM used OABI system call convention and numbers (kernel 2.4.1 for sure). Some time latter OABI was replaced by EABI – new syscall calling convention and syscall numbers. For some time Linux ARM EABI maintained compatibility with OABI. May be you problem somehow related for OABI/EABI mix. »
    https://www.linuxquestions.org/questions/linux-software-2/cross-compiling-software-for-arm-with-a-proprietary-toolchain-865514/

    ce que je trouve bizarre étant donné que ma machine utilise un gcc plutôt récent: 8.2.0
    Avez vous une idée de comment corriger cette erreur?
    Merci

    • cpb dit :

      Bonjour,

      Oui en effet c’est un message d’erreur bizarre.
      En principe la toolchain externe (lors de la seconde phase de compilation) se trouve dans $(TOPDIR)/../board/rpi-3/cross/usr/bin/ et on y voit entre autre :

      ls -l ../board/rpi-3/cross/usr/bin/
      [...]
      -rwxr-xr-x 3 cpb cpb 1019424 nov.   3 08:04 arm-buildroot-linux-gnueabihf-gcc-6.4.0.br_real
      [...]

      La toolchain est donc E-ABI (extended) et non O-ABI.

      Ce fichier est-il bien présent ?

      Dans le menu « Toolchain », on doit avoir les configurations suivantes :

      Toolchain type (External toolchain)  
      *** Toolchain External Options ***                                                  
      Toolchain (Custom toolchain)  
      Toolchain origin (Pre-installed toolchain)  
      ($(TOPDIR)/../board/rpi-3/cross/usr/) Toolchain path                                    
      ($(ARCH)-linux) Toolchain prefix                                                        
      External toolchain gcc version (6.x)  
      External toolchain kernel headers series (4.9.x)  
      External toolchain C library (glibc/eglibc) 
  24. tqhien dit :

    Merci beaucoup pour la mise à jour de l’article !

  25. ox223252 dit :

    Bonjour,
    Cet article est génial, mais je rencontre un problème avec la table des utilisateurs. Toute la compilation se passe bien ( pas d’erreurs affichés ), mais impossible de me connecter au système autrement qu’en root. Root se connecte sans problème mais un utilisateur défini dans un table ne fonctionne pas.

    voici le message :
    debug1: Authentications that can continue: publickey,password,keyboard-interactive
    Permission denied, please try again.
    albert@x.x.x.x’s password:

    • ox223252 dit :

      En fait en continuant à chercher j’ai trouvé, dans la table j’avais defini /bin/bash comme shell par défaut alors qu’il n’est pas dans la distro… bref.

  26. olivier dit :

    Bonjour Christophe,
    J’ai une petite question, j’essaye de faire la même avec la version PI3 B+ soc bcm2837b0.
    L’architecture est un A57 et pas A53 (j’ai changé cela dans la config).
    Au boot j’ai ce message :
    « end Kernel panic – not syncing: Attempted to kill init! exitcode=0x00007f00 »
    Un problème sur init , j’ai testé avec defconfig raspberrypi3 puis raspberrypi_64 mais ça plante toujours.
    Je précise aussi que j’ai testé avec un buildroot 2019 ( le 2018 me semblait un poil juste pour cette carte).
    Si tu as déjà testé , je suis preneur d’infos.
    D’avance merci.
    Olivier

    • cpb dit :

      Bonjour Olivier,
      J’ai fait une mise à jour de l’article ici.
      Finalement en utilisant Buildroot 2019.02 et en s’appuyant sur la configuration raspberry3_defconfig, l’image fonctionne sur Raspberry Pi 3B et 3B+.

URL de trackback pour cette page