Pour ceux qui ne le savent pas, je suis l’heureux possesseur d’une carte ARM nommée Odroid-C1. Cette carte a été fabriquée autour de 2014/2015 par Hardkernel.
La version du noyau fourni avec la carte est 3.10, avec énormément de patchs "made by hardkernel" pour que tout fonctionne bien. Seulement, depuis bientôt deux ans, il n’y a plus de mise à jour et déjà les mises à jour à l’époque n’étaient pas fréquentes et ne suivaient pas vraiment les patchs de sécurité.
Bref, j’ai donc décidé qu’il était temps d’essayer d’avoir une nouvelle version du kernel pour cette carte.
Le support de cette carte par la version principale de Linux (mainline) existe grace au projet communautaire Linux for Amlogic Meson (http://linux-meson.com/doku.php). Il a débuté fin 2015 avec ce patch (https://github.com/torvalds/linux/commit/4a69fcd3a10803854852481ab16031563d2d5381) qui a atterri dans la version 4.4 de Linux.
Avant de commencer
Je n’ai pas fait un test complet de la carte, il est donc possible que certaines choses ne fonctionnent pas correctement ou moins bien qu’avec le kernel d’origine.
Ce billet s’adresse à des personnes qui ont des bonnes connaissances de Linux et de son fonctionnement, il ne s’agit pas d’un tutoriel à appliquer tel que mais il doit être adapté pour votre cas (et carte).
Support matériel
La puce principale du C1 est un Amlogic S805, comme indiquée ici : https://wiki.odroid.com/odroid-c1/hardware/hardware.
Le tableau de la page http://linux-meson.com/doku.php nous donne le support de cette puce.
Attention, lors de l'écriture de ce billet, la sortie HDMI n'est pas supportée ! Ce nouveau noyau ne vous sera donc utile que si vous avez un usage sans écran (headless).
Solution rapide
Récupérer les fichiers sur le dépôt git suivant et sauter directement à la partie "installation".
Dans cette archive, vous trouverez le fichier uImage (le kernel) et les modules.
Préparation - Compilation
Avant tout, il faut préparer l’environnement de compilation, car on ne va pas compiler sur la carte ARM, ça serait bien trop long et ça risque de cramer la carte SD (même si on peut utiliser un disque usb pour éviter ça).
On va donc réaliser une cross-compilation depuis un PC, pour ce cas, je pars du principe que vous êtes avec une Debian Stretch, si ce n’est pas le cas, désolé :)
D’abord, il faut installer les paquets requis pour les différentes étapes
apt install gcc-arm-linux-gnueabihf build-essential flex bison libssl-dev bc u-boot-tools ccache fakeroot ncurses-devel libncurses-dev lzop gcc-arm-none-eabi git
Ensuite, on récupère la version stable de Linux (actuellement la version 5)
mkdir $HOME/compile cd $HOME/compile git clone https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git -b linux-5.0.y linux cd linux
La version 5.0 n’est pas une version avec un support à long terme, il faudra donc suivre les évolutions jusqu’à "tomber" sur une version dite LTS.
Avant tout, quelques variables d'environnement sont à définir
export PATH=/usr/lib/ccache:$PATH export CROSS_COMPILE=arm-linux-gnueabihf- export LOADADDR=0x00208000 export ARCH=arm export INSTALL_MOD_PATH=$HOME/compile/linux-modules/
La liste des options à activer pour avoir un kernel fonctionnel, voici le fichier « config » à placer dans le dossier à la racine des sources, il faut le nommer ".config".
Vous pouvez sélectionner et modifier les options en faisant make menuconfig. Dans la config proposée ici, la plupart des options du kernel sont configurées en mode "module" afin de faire une image assez petite tout en proposant une configuration qui permettrait de brancher une clef tv en usb ou une carte wifi sans problème sur la carte odroid.
Une fois les options définies, il faut générer l’image ainsi que les fichiers dit "device tree" et bien sûr, les modules.
make -j4 uImage dtbs modules
Je passe l’option j4 car j’ai un PC avec 4 cœurs ce qui permet d’accélerer le temps de compilation.
Une fois la compilation effectuée, on va faire
make modules_install
Et maintenant il ne reste plus qu’à copier les fichiers sur la carte odroid.
Les fichiers dont on va avoir besoin dans la compilation qu'on a effectuée sont :
- Le fichier « DTB », située ici : arch/arm/boot/dts/meson8b-odroidc1.dtb
- L’image du noyaux, située ici : arch/arm/boot/uImage
- les modules dans, située dans : arch/arm/lib/modules (ainsi que dans $INSTALL_MOD_PATH)
Installation
Si vous prenez les fichiers présents sur le git ou ceux de la compilation, l’installation est identique.
Les opérations de copie de fichiers (modules, kernel et DTB) peuvent être faite en branchant la carte SD sur un PC, ou depuis le C1 via le réseau ou une clef usb. La génération de l'initramfs doit elle être faite dans l'environnement cible, c'est-à-dire sur le C1. Elle nécessite un OS Debian ou Ubuntu sur le C1.
Dans le doute, faites les opérations depuis le C1, afin que les chemins correspondent à ceux de ce billet.
Les modules
On copie les fichiers des modules dans /lib/modules/ (si vous avez fait une compilation vous-mêmes ils sont dans : $INSTALL_MOD_PATH, sinon ils sont dans le répertoire lib/modules sur le git).
Le kernel, l’initramfs et le DTB
Le kernel est le fichier nommé uImage et le DTB meson8b-odroidc1.dtb, ces deux fichiers sont à copier dans le répertoire de boot de votre carte (en général /boot ou /media/boot).
Par souci de version, j’ajoute au fichier uImage le numéro de version (exemple uImage-3.10.148)
Génération de l’initramfs
Pour générer l’initramfs, on utilise les commandes suivantes :
VERSION=5.0.10 update-initramfs -c -k $VERSION mkimage -A arm -O linux -T ramdisk -C none -a 0 -e 0 -n uInitrd -d /boot/initrd.img-$VERSION /boot/uInitrd-$VERSION
Le boot.ini
Il reste ensuite à modifier le fichier boot.ini pour démarrer sur notre nouveau noyau.
Les seules modifications absolument nécessaires au boot.ini par rapport au boot.ini fourni par la version ubuntu-minimal de hardkernel sont les 3 lignes fatload.
Si vous avez des doutes, vous pouvez prendre celui-là comme exemple.
Pour utiliser le boot.ini qui est en exemple, il faut récupérer l’UUID de votre partition système (rootdev plus loin), pour ça on peut utiliser la commande suivante :
blkid $(mount | awk '/ \/ /{print$1}')
Il faut modifier les deux variables suivante pour correspondre aux informations de votre carte.
ethaddr rootdev
Il faut aussi changer vers la fin du fichier les noms des fichiers uImage et uInitrd.
fatload mmc 0:1 0x21000000 uImage-5.0.10 fatload mmc 0:1 0x22000000 uInitrd-5.0.10 #fatload mmc 0:1 0x21800000 meson8b_odroidc.dtb fatload mmc 0:1 0x21800000 meson8b-odroidc1.dtb
Post-conf (network)
Pour une raison inconnue, définir l’adresse MAC de la carte réseau dans le boot.ini ne suffit pas, il faut aussi la définir dans le fichier de configuration /etc/network/interfaces.
Il y a aussi un problème de stabilité si on laisse la carte réseau en gigabit, je force donc la carte en 100Mbit full duplex (merci Adventures with Linux).
iface eth0 inet dhcp hwaddress ether 00:1e:06:cb:e2:4d up ethtool -s $IFACE speed 100 duplex full autoneg off
Si vous utiliser NetworkManager il faudra faire les modifications dans NetworkManager.
Sur Ubuntu, NetworkManager est installé, et remplace ifupdown.
Cependant, en héritant de la conf dans /etc/network/interfaces.d/eth0 en lecture seule, il n'est pas capable de positionner l'adressse Mac de l'interface.
De plus, une fois l'interface active, il n'est pas possible de changer son adresse... or vous êtes connecté à l'odroid via le réseau en ssh ! La solution consiste a ajouter le paquet ifupdown : apt install ifupdown.
Après le redémarrage, la commande ifup sera lancée par le service networking, et l'adresse Mac sera positionnée en accord avec le fichier /etc/network/interfaces.d/eth0.
L'autre solution (non testée) aurait été une gestion complète via NetworkManager, en supprimant le fichier /etc/network/interfaces.d/eth0 et en une ligne mac-address dans la section [Ethernet] du fichier /etc/NetworkManager/system-connections/ethernet-eth0.
Il manque un module pour chez moi !
Si vous avez besoin de modules ou d’option pour le noyaux qui ne sont pas disponible dans le binaire mis à disposition, merci d’ouvrir un ticket sur le gitlab.
Ressources complémentaires
- Compilations et tests automatisée de différents noyaux pour le C1 : https://kernelci.org/boot/meson8b-odroidc1/
- Guide complet pour compiler un nouveau noyau sur ARM : https://github.com/umiddelb/armhf/wiki/How-To-compile-a-custom-Linux-kernel-for-your-ARM-device
- Le wiki officiel : https://wiki.odroid.com/odroid-c1/odroid-c1
- Le forum Odroid : https://forum.odroid.com/viewforum.php?f=111
Remerciement
Merci à Id2ndR pour les remarques et amélioration de l’article.
Merci à Meriem pour les relectures :)
1 De Hector -
Bonjour,
J'ai suivi les étapes, mais je n'obtiens qu'un écran noir au démarrage, sans autre information.
2 De aplufr -
Bonjour Hector,
Si tu utilises la sortie HDMI celle ci n'est pas, encore, supportée, c'est indiqué au début du billet.
Le tableau ici : http://linux-meson.com/doku.php indique ce qui est pris en charge par le noyeau le plus recent, il faut regarder la colonne S805.
La carte réseau devrait fonctionner normalement par contre.
3 De Hector -
ah bah oui, j'étais passé directement à la partie installation.
Merci pour ta réponse.
4 De Sagittarius -
Du nouveau avec les derniers noyaux et les prises en charge meson ?
Merci
5 De APLU -
Je ne sais pas, ma carte a fini par tomber en panne j’ai arrêté de compiler des versions du kernel du coup.
6 De Carambola -
Bonjour,
Merci beaucoup pour tes instructions !
J'ai suivi scrupuleusement tes indications, mais le kernel pré-compilé que tu fournis sur Gitlab ne boot pas chez moi. La LED bleue reste fixe.
J'ai pourtant préalablement booté sur un autre kernel fonctionnel, pour avoir mon système démarré et être en mesure de générer un initrd (et un uInitrd) pour ta version de kernel.
J'ai donc voulu réitérer de mon côté, et je suis parti sur la 6.0.11.
Même constat : même en fournissant le bon uImage, le bon uInitrd et le bon DTB (qui bizarrement semble différent de celui fourni par Hardkernel, bien que le hardware ne change pas) dans le boot.ini, la led bleue reste fixe alors qu'elle est censée faire un heartbeat.
Une idée de ce que j'ai pu rater ? Je parle du kernel que tu fournis, pour éviter les éventuelles bêtises que j'ai pu faire en compilant l'autre de mon côté.
Pour ceux qui avaient eu plus de chance que moi en testant le kernel de APLU, voici une maigre contribution de ma part. Le kernel 6.0.11 compilé avec la toolchain Linaro/ARM 10.3-2021.07, avec :
```
make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabihf- multi_v7_defconfig
make -j16 ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabihf- LOADADDR=0x00208000 uImage dtbs modules
make -j16 ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabihf- LOADADDR=0x00208000 modules_install
```
Il y a le uImage dedans, et les modules. Suivez les instructions d'APLU pour générer l'initrd et le uInitrd.
Lien de DL (30j de rétention) : https://ufile.io/9zan48jo
7 De Carambola -
Je viens de me rendre compte, que j'avais oublié d'inclure le DTB dans mon archive.
Donc je viens de la corriger et de l'uploader.
Voici le lien : https://ufile.io/ozbir5fk
Suivez les instructions d'APLU et j'espère que ça marchera pour vous.
N'hésitez pas à répondre en-dessous pour me dire si ça fonctionne pour vous.