LINUX FROM SCRATCH ! Embedded Linux Hugo Descoubes – Janvier 2014
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Nous allons maintenant nous intéresser à du développement GNU/Linux bas niveau sur une plateforme donnée. Nous travaillerons sur un SoC TI AM335x à architecture ARM Cortex-A8 (le choix de TI est lié aux compétences déjà présentes à l’école) intégré sur la plateforme BeagleBone black (projet beagle board). Sachez que de nombreuses autres plateformes équivalentes existent sur le marché (raspberryPI, beagleboard, pandaboard …) : http://beagleboard.org/products/beaglebone%20black
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Observons rapidement les interfaces matérielles proposées par le SoC AM335x de la famille Sitara. Ce processeur fait de la BBB (BeagleBoneBlack) une plateforme très adaptée au domaine industriel (contrairement à la raspberryPI, beagleboard …) : http://www.ti.com/product/am3359
Observons maintenant les interfaces proposées par la board : Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Observons maintenant les interfaces proposées par la board : http://elinux.org/Beagleboard:BeagleBoneBlack
Target Embedded system Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Intéressons-nous maintenant aux interfaces de communications avec le chip dans une optique de développement. Comme beaucoup d’architectures autour de GNU/Linux embarqué, deux interfaces nous intéressent : Serial : interface série bas niveau via UART permettant une communication avec le bootloader et le système (shell distant). Une interface via SSH est également possible (secure shell). TFTP : Trivial FTP (transferts FTP moins sécurisés transportés sur UDP) permettant le transfert de fichiers entre le système host et le système embarqué cible. TFTP USB to UART Host system Target Embedded system
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Même si cela n’est pas une obligation, il est très fortement conseillé de travailler sous GNU/Linux côté machine host. Afin d’établir une communication via liaison série ou USB/série avec un système GNU/Linux et obtenir une interface utilisateur, plusieurs options s’offrent à nous (minicom, kermit, putty, gtkterm …). Contrairement à Windows, aucune installation de driver n’est nécessaire, c’est magique. USB/serial : afin de voir apparaître vos liens USB/Serial sous GNU/Linux, observer les derniers devices connectés présents dans /dev. Les interfaces génériques tty (teletypewriter) permettent des communications basées sur des échanges de caractères.
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Nous travaillerons dans notre cas avec minicom, un utilitaire robuste qui offre notamment comme avantage de proposer une interface très simple depuis le shell. Installons l’outil si ce n’est pas déjà fait et effectuons une configuration par défaut (sous minicom taper sur ctrl+a, relâcher puis taper z pour accéder à l’aide) :
Editons une configuration propre à la communication UART : Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH La configuration précédemment créée a été dans notre cas sauvée par défaut dans /etc/minicom (minicom –h pour connaître le chemin par défaut). Observons le contenu du fichier de configuration généré minirc.dfl : Editons une configuration propre à la communication UART :
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Alimenter maintenant la BBB, ouvrir minicom avec la configuration précédemment créée et observer le retour côté shell. Voilà … nous pouvons observer la phase de boot du système :
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Voici maintenant un petit exercice. La BBB propose deux interfaces série de communication avec le système, une via UART (com. avec bootloader et GNU/Linux) et l’autre via une émulation de liaison série par USB (com. GNU/Linux, configurée au démarrage du kernel). Configurer minicom pour la seconde communication et nommer la configuration linuxBBB ! Bootloader and GNU/Linux Only GNU/Linux (USB device) Only GNU/Linux Bootloader and GNU/Linux
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Intéressons-nous maintenant à mettre en place un serveur TFTP côté host et validons un transfert de fichier vers la BBB. Vous devez dans un premier temps télécharger les utilitaires nécessaires côté host : Créer un répertoire tftp (ou autre nom) dans l’arborescence du système de fichiers de votre projet et modifier les droits d’accès. Editer dans ce répertoire un fichier quelconque avec un contenu quelconque : sudo apt-get install tftp tftpd xinetd cd ~/elinux/ mkdir tftp sudo chmod 777 tftp/ cd tftp/ gedit helloworld&
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Editer le fichier nommé tftp ci-dessous et le copier dans /etc/xinetd.d/. Le chemin associé à l’argument server_args est à adapter en fonction de votre machine et du répertoire précédemment créé : Stopper le serveur xinetd (eXtended InterNET Daemon) et le redémarrer. Votre serveur de fichiers est alors lancé : sudo service xinetd stop sudo service xinetd start sudo service xinetd status
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Nous allons maintenant configurer le réseau côté BBB et récupérer le fichier précédemment créé côté host depuis un client tftp côté board. Configurer le réseau sur la BBB pour travailler sur le réseau école (plage IP libres de 172.24.123.20 jusqu’à 172.24.123.40, masque de sous réseau 255.255.0.0 et passerelle 172.24.0.1). Valider votre configuration via la commande ping : Une seconde solution est d’éditer le fichier /etc/network/interfaces puis d’invoquer les commandes ifdown et ifup afin d’activer la configuration (ou automatisation via ifstate).
S’aider du memento en ligne proposé par Free Electrons : Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Un problème (qui n’en est pas forcément un) souvent rencontré dans le monde de Linux embarqué est que travaillons souvent sans IHM. Du coup, il est impossible d’invoquer un éditeur de texte classique (Emacs, gedit …). Nous allons utiliser l’éditeur de texte plein écran vi (Visual Interface). Editer le fichier interfaces ci-dessous (doc. /usr/share/doc/ifupdown/example/network-interfaces) : S’aider du memento en ligne proposé par Free Electrons : http://free-electrons.com/doc/vi_memento_fr.pdf auto lo iface lo inet loopback auto eth0 iface eth0 inet static address 172.24.123.20 netmask 255.255.0.0 gateway 172.24.0.1
Il ne reste plus qu’à récupérer le fichier créé côté host sur la BBB. Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Il ne reste plus qu’à récupérer le fichier créé côté host sur la BBB. Second petit exercice sous vi, éditer un fichier helloWorld.c réalisant un printf de ‘’hello world !\n’’, le compiler et l’exécuter. Pour information, contrairement à Angstrom, beaucoup de distributions rencontrés dans le domaine de l’embarqué n’embarque pas d’outils de développement (système autonome après démarrage de l’applicatif).
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH A partir de maintenant, les interfaces de communication avec la plateforme cible sont mises en place. Nous allons maintenant étudier la procédure de compilation et de chargement d’un système GNU/Linux complet pour la beagleBone Black (procédure et concepts identiques sur les autres plateformes Linux embarqué). Comme pour beaucoup de développement dans le monde de Linux embarqué, nous travaillerons sans IDE (mode root seulement en dernier recours). Sachez qu’il est tout de même possible de travailler sous IDE, notamment Eclipse (lourdeur de configuration et d’interfaçage des outils pour de gros projets pré-édités comme Linux et les distributions associées).
Wiki officiel projet BBB : Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Comme pour beaucoup de plateformes, une recherche sur le web des projets libres les plus mûres est indispensable (version stable et patchs kernel). Observons une liste non exhaustive des principaux projets concernant la BBB (être prudent quant à l’activité et le suivi des solutions sur les sites visés) : Wiki officiel projet BBB : http://elinux.org/Beagleboard:BeagleBoneBlack#Software_Resources Wiki officiel pour la compilation du kernel sur BBB : http://elinux.org/Building_BBB_Kernel Projet proposé par Robert Nelson (contributeur kernel Linux) : http://eewiki.net/display/linuxonarm/BeagleBone+Black#BeagleBoneBlack-LinuxKernel Projet libre inspiré des précédents : http://the8thlayerof.net/2013/10/16/beagle-bone-black-notes-how-to-build-a-kernel-for-a-beagle-bone-black-from-scratch-part-1/
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Durant la suite de cette partie du cours, nous nous inspirerons fortement des tutoriels proposés par Robert Nelson et le wiki officiel pour le projet BBB. Celui-ci se veut légèrement plus exhaustif que les autres. Première chose à faire, récupérer une toolchain ou de façon plus générique une ABI : ABI (Application Binary Interface ) : boîte à outils pour la génération, la manipulation et l’analyse de codes compilés. Il existe plusieurs variantes : EABI (Embedded ABI) tenant compte de l’hétérogénéité des architectures dans l’embarqué, EABIHF (EABI Hardware Float) supportant à la compilation les formats flottant de façon matérielle si supporté par l’architecture cible … API (Application Programming Interface) : interface entre les bibliothèques et le code source (ne pas confondre avec ABI).
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Une toolchain est un outil de développement logiciel proposant généralement sur système GNU plusieurs services : Compilateur ou compiler (cross-compiler ou native-compiler) : compilateur gcc-like différent d’une famille de CPU à une autre (ARM, x86, MIPS, PPC …) GNU Binutils (GNU Binary Utilities) : assembler (as), linker (ld) et utilitaires pour la manipulation et l’analyse de fichiers binaires compilés le plus souvent au format ELF (objdump, readelf, nm, strip …)
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH C library : bibliothèque C proposant généralement une API POSIX standard de programmation (services haut niveau et appels système). Dans le monde de Linux pour l’embarqué, plusieurs familles de bibliothèques peuvent être rencontrées (bibliothèques optimisées) : glibc, eglibc (embedded glibc), uClibc … Support optionnel d’autres langages (C++, JAVA, Fortran, ADA, Objective-C) Debugger (gdb-like) Pour information, dans le monde de Linux embarqué, le choix de la toolchain peut être problématique. Il est assez courant de travailler avec des versions anciennes mais stables de toolchain. Problèmes à découvrir au fil des projets.
CodeSourcery (Mentor Graphics) : projet très bien suivi et maintenu. Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Il existe deux grandes stratégie afin d’obtenir une cross-toolchain ou chaîne de compilation croisée. Récupérer une toolchain précompilée (souvent pour machine host) ou à compiler souvent par outils d’automatisation (Crosstool-NG, Crossdev …). Observons les principaux projets proposant des toolchains précompilées : CodeSourcery (Mentor Graphics) : projet très bien suivi et maintenu. Linaro : projet très bien suivi et maintenu proposant notamment des toolchains optimisées pour du développement sur architecture ARM (Cortex A8, A9 …) DENX ELDK (Embedded Linux Development Kit), Scratchbox …
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH En suivant le tutoriel de Robert Nelson, récupérer la chaîne de compilation en se plaçant dans le répertoire /elinux/work/toolchain/linaro/ de l’arborescence de TP : Contrairement au tutoriel, nous ne modifierons pas la variable d’environnement CC mais PATH, ceci permettra de pouvoir plus facilement continuer à réaliser de la compilation native : cd ~/elinux/work/toolchain/linaro/ wget -c https://launchpad.net/linaro-toolchain-binaries/trunk/2013.10/+download/gcc-linaro-arm-linux-gnueabihf-4.8-2013.10_linux.tar.xz tar xJf gcc-linaro-arm-linux-gnueabihf-4.8-2013.10_linux.tar.xz export PATH=/<cross_compiler_path>/bin/:$PATH
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Cross-compiler un fichier C retournant un helloworld sur le shell, copier via tftp le binaire de sortie sur la BBB puis l’exécuter. Essayer de l’exécuter côté host, vous constaterez une insulte de la part du système. En effet, le format de fichier ELF inclut une en-tête de fichier spécifiant l’architecture cible : arm-linux-gnueabihf-gcc helloworld.c –o helloworld_dynamic.out
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Se placer dans le répertoire ~/elinux/work/kernel/, récupérer, patcher puis compiler le kernel, le device tree et les modules. Suivre le tutoriel officiel BBB (http://elinux.org/Building_BBB_Kernel). Attention, nous allons générer une image compressée du kernel, cette solution diminue le temps de boot du kernel une fois en RAM, mais accélère le temps de chargement en RAM par le bootloader (étape longue, notamment sur MMC/SDcard, ~500ms dans notre cas) : cd ~/elinux/work/kernel/ git clone git://github.com/beagleboard/kernel.git cd kernel git checkout 3.8 ./patch.sh cp configs/beaglebone kernel/arch/arm/configs/beaglebone_defconfg wget http://arago-project.org/git/projects/?p=am33x-cm3.git\;a=blob_plain\;f=bin/am335x-pm-firmware.bin\;hb=HEAD -O kernel/firmware/am335x-pm-firmware.bin export PATH=/<cross_compiler_path>/bin/:$PATH make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- beaglebone_defconfig make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage dtbs –j2 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules –j2 mkdir ../deploy cp arch/arm/boot/zImage ../deploy cp arch/arm/boot/dts/am335x-boneblack.dtb ../deploy
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Intéressons maintenant au root file system (système de fichiers racine) ou rootfs (présent en user space). Avant tout, sachez que le rootfs déployé pour une distribution donnée est indépendant du kernel. Nous pourrions, si nous le souhaitons, développer et déployer un rootfs maison (/foo /bar /toto /titi …). Néanmoins, étudions le rootfs majoritairement rencontré sur grand nombre de systèmes UNIX ou UNIX-like : / : répertoire racine (à comparer aux lecteurs C:\, D:\ … sur systèmes Windows). Un système de fichiers étant construit comme un arbre, root ou racine représente donc symboliquement la racine de l’arbre.
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH /home : répertoires associés aux comptes utilisateurs (tout système UNIX est multi-utilisateurs) /bin (binaries) : fichiers binaires exécutables implémentant les commandes ou composants système supportés par la distribution /usr (unix shared resources) : second niveau de hiérarchie du fs pour les services partagés (/usr/bin, /usr/sbin, /usr/lib bibliothèques locales à /usr). Contient notamment les headers kernel, important pour la suite de l’enseignement.
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH /dev (device) : fichiers d’interfaces avec les périphériques physiques ou virtuels. Par exemple les interfaces SCSI (USB, S-ATA via /dev/sdXXX), terminaux (/dev/ttyXXX) … /etc (Editable Text Configuration) : fichiers de configuration consultables et éditables du système et des services utilisateurs /lib (libraries) : bibliothèques système nécessaires aux exécutables présents dans /bin et /sbin. Notamment la célèbre bibliothèque standard du c (fichier libc.so.6) :
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH /proc (processes) : fichiers virtuels accessibles en lecture documentant le système et les différents processus en cours /sbin (System Binaries) : commandes pour l’administration système (ifconfig, route, shutdown …) /media point de montage des supports de stockage amovibles, /var pour les fichiers à contenu changeant (historiques de messagerie …), /mnt (points de montage manuel hors /media), /boot (fichiers d’amorçage), /tmp (temporary) accessible par tous, peut notamment éviter de surcharger les répertoires utilisateurs présents dans /home, …
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Récupérer un système de fichiers ou rootfs debian 7.3 (wheezy) pré-compilé pour architecture ARM. Nous verrons par la suite comment générer notre propre rootfs (partie BSP Linux). Se placer dans /elinux/work/rootfs/debian/ (login et mdp : root) : Juste par curiosité, extraire le file system dans un répertoire temporaire et observer son contenu (supprimer le répertoire et son contenu par la suite) : http://elinux.org/BeagleBoardDebian wget -c https://rcn-ee.net/deb/minfs/wheezy/debian-7.3-minimal-armhf-2013-12-18.tar.xz tar xf debian-7.3-minimal-armhf-2013-12-18.tar.xz cd debian-7.3-minimal-armhf-2013-12-18/ mkdir rootfs tar -xvf armhf-rootfs-debian-wheezy.tar –C rootfs/ cd rootfs
Embarqué : U-Boot (Universal Bootloader), Barebox … Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Le travail élémentaire d’un bootloader est de charger en mémoire principale volatile (accès rapide, souvent nommée RAM) un firmware présent en mémoire secondaire ou mémoire de stockage de masse (larges ressources mais accès lents : hard disk, SDcard, CD, eMMC …). Néanmoins, beaucoup de bootloader proposent des services avancés de configuration et de communication (chargement via tftp, console …). Le firmware chargé peut-être un OS ou un applicatif compilé quelconque. Observons quelques un des principaux bootloader rencontrés : Monde du PC : GNU GRUB (Grand Unified Bootloader), LILO (Linux Loader), WINLOAD (bootloader Windows Vista) … Embarqué : U-Boot (Universal Bootloader), Barebox …
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Plusieurs stratégies de boot et de chargement de firmware en mémoire (volatile ou non-volatile) existent lorsque nous développons sur un processeur à architecture CPU : Bootloader : In-Circuit Emulator (sonde d’émulation JTAG) : solution très rencontrée dans le domaine de l’embarqué External mass storage External or Internal RAM processor Bootloader firmware JTAG support External ICE External or Internal RAM processor External or internal mass storage firmware
Debugger matériel (via sonde d’émulation) Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Par exemple, l’environnement de développement DS-5 proposé par ARM est un outil très puissant de debuggage et de profilage (cf. Intel Parallel Studio pour architecture Intel x86) mais très coûteux (développement de bootloader, accélération phase de boot …). Cet outil propose notamment : Debugger matériel (via sonde d’émulation) Outils de trace et de profilage Simulateur temps réel, IDE, compilateur optimisé, support technique …
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH U-Boot est en 2013 le bootloader le plus rencontré dans le domaine de Linux embarqué (distribué par DENX). Il s’agit d’un projet Opensource supportant un très grand nombre d’architectures CPU (ARM, x86, MIPS, PPC …) et de cartes cibles (beaglebone, raspberryPI …). U-Boot propose une console, typiquement via liaison série, permettant d’interagir avec lui via la manipulation de variables d’environnement internes par envoi de commandes. Possibilité de booter le système depuis plusieurs sources tel que Flash NAND, eMMC, MMC/SDcard, via tftp …
Manipulation mémoires NOR et NAND (cp, erase, nand read …) Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Observons quelques une des principales commandes supportées par U-Boot (http://www.denx.de/wiki/U-Boot/Documentation) : Manipulation variables d’environnement : printenv (affiche toutes les var. env.), setenv [name] [value] (ajoute/modifie var. env.), setenv [name] (supprime var. env.), saveenv (sauvegarde persistante des var. env.) … Manipulation mémoires NOR et NAND (cp, erase, nand read …) Interaction avec le système : help (listes des commandes), help [commande], reset (reset CPU), bdinfo (board info) …
BeagleBone Black Architecture Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Sur BBB, comme pour beaucoup d’architectures, nous rencontrons une stratégie de boot à plusieurs étages. Rappelons l’architecture interne du chip et de la board : AM335x Architecture BeagleBone Black Architecture
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH La stratégie de boot sur famille OMAP de TI, différente sur d’autres architectures, propose plusieurs étages de chargement, notamment le second étage de boot nommé X-Loader (MLO ou Memory Locator chez TI) qui est une version sans fioritures de U-Boot : CPU invoke the reset interrupt vector To start code of on-chip ROM loader http://omappedia.org/wiki/Bootloader_Project http://processors.wiki.ti.com/index.php/AM335x_U-Boot_User's_Guide Off-chip MMC Kernel Decompresses kernel into off-chip SDRAM Set up peripherals (HDMI, I2C, USB …) Mount linux rootfs (userland) … On-chip ROM 1st stage loader Minimal clocks, fs support (FAT16), memory MMC and peripherals configuration Search booting devices (often by GPIO config. bits) Load x-loader (MLO) into on-chip SRAM and execute it Off-chip MMC 2nd stage X-Loader (MLO) Initializes clocks, main memory (DDR) and sets up pin muxing Load U-Boot into off-chip SDRAM and execute it Off-chip MMC 3rd stage U-Boot Additionnal platform Initialization (network, UART …) Sets the kernel boot arguments Passes control to the kernel image
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Observons le contenu des mémoires physiques de notre plateforme avant et après la phase d’amorçage :
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Suivre le tutoriel en ligne, récupérer les sources de U-Boot (projet git de DENX), appliquer les patches propres à notre plateforme puis compiler le kernel. Ne pas oublier de vérifier les chemins présents dans la variable PATH (travailler dans /elinux/work/uboot/) : Les binaires de sortie se trouveront à la racine du répertoire u-boot : MLO et u-boot.img. cd ~/elinux/work/uboot/ git clone git://git.denx.de/u-boot.git cd u-boot/ git checkout v2013.10 -b tmp wget https://raw.github.com/eewiki/u-boot-patches/master/v2013.10/0001-am335x_evm-uEnv.txt-bootz-n-fixes.patch patch -p1 < 0001-am335x_evm-uEnv.txt-bootz-n-fixes.patch export PATH=/<cross_compiler_path>/bin/:$PATH make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- am335x_evm_config make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Avant de commencer à préparer la phase de boot (configuration U-Boot), nous devons partitionner la SDcard. Il existe de nombreux scripts sur la toile permettant de formater des SDcards, dans notre cas, nous travaillons avec un petit utilitaire très simple et efficace utilisant la bibliothèque GTK+ (cf. interface GNOME …) : GParted (GNU Parted) Connecter la SDcard à la machine host via dongle USB/MMC ou directement sur un lecteur MMC (Multi Media Card). Attention, dans le second cas de figure, ne pas oublier de monter des lecteurs dans /media/ ou /mnt/ (commande mount) après partitionnement :
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Identifier le device associé à votre média MMC, lancer gparted en root et suivre le tutoriel ci-dessous :
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Identifier le device associé à votre média MMC, lancer gparted en root et suivre le tutoriel ci-dessous :
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Une fois partitionnée et formatée, copier les binaires cross-compilés de U-Boot et du MLO à la racine de la carte MMC/SDcard dans la partition boot formatée en FAT16. Placer la carte dans le lecteur de la BBB et effectuer un reset matériel de la plateforme (appuyer sur une touche afin d’interrompre la phase de boot et obtenir une console U-Boot) : cd ~/elinux/work/uboot/u-boot/ cp u-boot.img /media/boot/ cp MLO /media/boot/ sync
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH L’adresse de chargement du kernel proposée n’est pas le fruit du hasard (0x8020000). Observons rapidement la datasheet du SoC AM335x de TI (http://www.ti.com/lit/ug/spruh73i/spruh73i.pdf) : AM335x Architecture
Voici maintenant quelques questions : Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Copier dans le répertoire associé au serveur tftp côté host les fichiers suivants générés durant la phase de compilation du kernel (~/elinux/work/kernel/kernel/deploy/): Voici maintenant quelques questions : Pourquoi l’adresse de boot n’est-elle pas 0x80000000 ? Pourquoi est-on obligé de formater la partition contenant U-Boot et le MLO en FAT16 ? Qu’elle variable d’environnement U-Boot est à modifier afin de changer le nom du fichier appelé par défaut au boot (uEnv.txt) ?
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Nous allons maintenant jouer un peu avec U-Boot. Premier exercice, nous allons récupérer le kernel compilé par tftp et le charger en RAM. Démarrer le serveur tftp côté host, configurer le réseau sous U-Boot côté cible et effectuer un ping de l’adresse host. Charger l’image du kernel compressé en RAM puis booter sur l’adresse de chargement : U-Boot# setenv ipaddr 172.24.123.20 U-Boot# printenv ipaddr U-Boot# setenv netmask 255.255.0.0 U-Boot# setenv gatewayip 172.24.0.1 U-Boot# setenv serverip 172.24.123.15 U-Boot# ping ${serverip} U-Boot# tftp 0x80200000 zImage; U-Boot# bootz 0x80200000
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Il faut savoir que le bootloader a également possibilité de passer des paramètres de boot à l’amorçage du kernel (boot arguments consultables dans /proc/cmdline). Certains de ces arguments peuvent également être inclus à la compilation du noyau (cf. fichier /Documentation/kernel_parameters.txt présent dans le système de fichiers du kernel). La plupart de ces paramètres sont passés sous forme de chaîne de caractères et sont souvent nommés ATAGS parameters (Authoring Tool Accessibility Guidelines) :
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Nous allons maintenant automatiser la procédure de configuration de U-Boot avant de lancer la phase de d’amorçage. Editer et analyser le fichier uEnv.txt suivant : #u-boot network configuration and tftp boot (BeagleBone Black) #u-boot ip configuration for BBB ipconfig=setenv ipaddr 172.24.121.20; setenv netmask 255.255.0.0; setenv gatewayip 172.24.0.1; setenv serverip 172.24.123.15, ping ${serverip} ipprint=printenv ipaddr; printenv netmask; printenv gatewayip; printenv serverip #boot parameters configuration console=ttyO0,115200n8 mmcargs=setenv bootargs console=${console} #tftp to ram load and boot uenvcmd=run ipconfig; run ipprint; tftp 0x80200000 zImage; tftp 0x80F80000 am335x-boneblack.dtb; bootz 0x80200000 - 0x80F80000
zImage (image compressée du kernel) dans /media/boot/ Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Intéressons nous à charger en RAM le kernel ainsi que le device tree depuis la MMC/SDcard (cf. tutoriel en ligne). Une fois le kernel chargé et lancé, nous booterons le système sur un simple helloword compilé en statique et finissant par ‘’while(1);’’. Au démarrage de U-Boot, s’assurer que la SDcard soit bien reconnue et vérifier le numéro associé au device. Copier les fichiers suivants sur la SDcard : zImage (image compressée du kernel) dans /media/boot/ am335x-boneblack.dtb (device tree binary) dans /media/boot/dtbs helloworld_static.out (fichier c helloworld cross compilé en statique) dans /media/rootfs/
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Editer, analyser puis copier sur la MMC/SDcard le fichier uEnv.txt ci-dessous. Rebooter le système : #u-boot mmc (SDcard) boot kernel_file=zImage #mmc (SDcard for bbb) parameters mmcdev=0 mmcpart=1 loadzimage=load mmc ${mmcdev}:${mmcpart} ${loadaddr} ${kernel_file} loadfdt=load mmc ${mmcdev}:${mmcpart} ${fdtaddr} /dtbs/${fdtfile} #helloworld boot optargs=quiet init=/helloworld_static.out console=ttyO0,115200n8 mmcroot=/dev/mmcblk0p2 rw mmcrootfstype=ext4 rootwait fixrtc mmcargs=setenv bootargs console=${console} root=${mmcroot} rootfstype=${mmcrootfstype} ${optargs} #boot commands for compressed image kernel uenvcmd=run loadzimage; run loadfdt; run mmcargs; bootz ${loadaddr} - ${fdtaddr}
Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH Extraire les rootfs debian 7 précédemment téléchargé dans la seconde partition de la SDcard (/media/rootfs/). Editer, analyser puis copier sur la SD le fichier uEnv.txt ci-dessous. Rebooter le système, vous voilà sur un système debian (login: root, mdp: root): #u-boot mmc (SDcard) boot kernel_file=zImage #mmc (SDcard for bbb) parameters mmcdev=0 mmcpart=1 loadzimage=load mmc ${mmcdev}:${mmcpart} ${loadaddr} ${kernel_file} loadfdt=load mmc ${mmcdev}:${mmcpart} ${fdtaddr} /dtbs/${fdtfile} #systemd boot optargs=quiet init=/lib/systemd/systemd console=ttyO0,115200n8 mmcroot=/dev/mmcblk0p2 rw mmcrootfstype=ext4 rootwait fixrtc mmcargs=setenv bootargs console=${console} root=${mmcroot} rootfstype=${mmcrootfstype} ${optargs} #boot commands for compressed image kernel uenvcmd=run loadzimage; run loadfdt; run mmcargs; bootz ${loadaddr} - ${fdtaddr}
Lancement script linuxrc : charge les modules complémentaires Plateforme –Interfaces – Cross-compiler – Kernel – rootfs – bootloader – Helloworld - debian LINUX FROM SCRATCH A titre indicatif, sur grand nombre de distributions Linux pour PC, nous pouvons trouver une phase de boot structurée en plusieurs étapes comme suit : Chargement bootloader : le bootloader est un chargeur binaire d’amorçage d’un système d’un support source (hard disk, USB, MMC/SDcard …) vers la RAM du processeur (mémoire principale) Chargement kernel : kernel compilé avec un jeu de services minimaliste, notamment les drivers (solution plus robuste) Chargement initrd (Initial Ram Disk, argument passé au kernel par le bootloader) : charge en RAM un système minimal ainsi que les modules strictement nécessaires au système (cf. /boot) Lancement script linuxrc : charge les modules complémentaires Lancement processus init : processus souvent avec PID n°1
Merci de votre attention !