Compiler son propre noyau Linux

Published: 18-07-2015

Updated: 23-02-2016

By: Maxime de Roucy

tags: gentoo kernel

Quelques notes concernant la configuration, la compilation et l’installation d’un noyau Linux sous Gentoo. J’utilise Gentoo mais ces instruction sont valable sur n’importe quelle distribution.

Je n’utilise pas d’initramfs, je ne compile que les fonctionnalité dont mon système à besoins et je les compile en dure dans le noyau.

L’initramfs (successeur d’initrd) n’est nécessaire que lorsque des fonctionnalité nécessaire au démarrage du système sont compilé en temps que module. Je pourrais garder quelques modules séparés du moment qu’il ne sont pas requis au démarrage du système sans pour autant avoir besoins d’initramfs.

Je compile toutes les fonctionnalité en dure (pas de module) car la machine est un serveur :

Le truc c’est de savoir quoi garder et quoi supprimer de la configuration du noyau. La documentation gentoo sur la compilation du noyau est bien faite, je vous encourage fortement à la lire.

listing matériel

Pour savoir quoi activé et quoi désactiver utiliser lspci. Certains utilise aussi lshw, ce n’est pas mon cas.

lspci -v permet de connaitre le module noyau actuellement utilisé pour gérer le matériel ; même si le « module » est compilé en dure dans le noyau. Ça permet ensuite de rechercher le nom du module dans la configuration et de l’activer.

root@server # lspci -v
…
03:00.0 Ethernet controller: Qualcomm Atheros AR8162 Fast Ethernet (rev 10)
Subsystem: ASUSTeK Computer Inc. Device 200f
Flags: bus master, fast devsel, latency 0, IRQ 29
Memory at f7c00000 (64-bit, non-prefetchable) [size=256K]
I/O ports at e000 [size=128]
Capabilities: <access denied>
Kernel driver in use: alx
Kernel modules: alx
…

Il est parfois intéressant de jeter un œuil à la matrice (non officiel) de compatibilité Debian. Copier/Coller la sortie de la commande lspci -n sur le site Debian hcl, celui-ci vous indiquera si votre matériel est supporté et si oui quel driver utiliser.

Généralement lspci est suffisant car la plupart des matérielles utilise ce bus. Cependant on peut aussi vérifier/ajouter le matériel non pci, par exemple USB avec lsusb. Une liste de bus peut être trouvée sur le site LKDDb (Linux Kernel Driver DataBase).

carte son

Source : Forum Archlinux

Sur ma machine j’ai une carte son gérée par le driver « snd_hda_intel ».

root@server # lspci -v
…
00:1b.0 Audio device: Intel Corporation System Controller Hub (SCH Poulsbo) HD Audio Controller (rev 07)
Subsystem: Intel Corporation Device 8119
Flags: bus master, fast devsel, latency 0, IRQ 22
Memory at d8010000 (64-bit, non-prefetchable) [size=16K]
Capabilities: [50] Power Management version 2
Capabilities: [70] Express Root Complex Integrated Endpoint, MSI 00
Capabilities: [100] Virtual Channel
Capabilities: [130] Root Complex Link
Kernel driver in use: snd_hda_intel
…

J’ai donc activé ce driver mais celui-ci gère plusieurs cartes dont le support peut être activé/désactivé au cas par cas. Pour savoir de quelle carte son je dispose j’ai été récupéré les information retournée par le driver :

root@server # grep '^Codec' /proc/asound/card0/codec\#0
Codec: Realtek ALC260
root@server # grep ' ALC' -r **/Kconfig
…
arch/mips/alchemy/Kconfig:      select ALCHEMY_GPIOINT_AU1000
sound/pci/hda/Kconfig:    snd-hda-intel driver, such as ALC880.
sound/soc/codecs/Kconfig:       tristate "Realtek ALC5623 CODEC"
sound/soc/codecs/Kconfig:       tristate "Realtek ALC5631/RT5631 CODEC"
sound/soc/samsung/Kconfig:      tristate "SoC AC97 Audio support for LN2440SBC - ALC650"
sound/soc/samsung/Kconfig:        with the ALC650.
sound/soc/tegra/Kconfig:        tristate "SoC Audio support for Tegra boards using an ALC5632 codec"
…

J’ai activé « CONFIG_SND_HDA_CODEC_REALTEK » et désactivé les autres codecs.

CONFIG_SND_HDA_CODEC_REALTEK:
Say Y or M here to include Realtek HD-audio codec support in snd-hda-intel driver, such as ALC880.

configuration

root@server # cd /usr/src/linux
root@server # make help
…
menuconfig      - Update current config utilising a menu based program
…

root@server # make menuconfig

Une version en ligne de make help est disponible sur le site www.kernel.org.

outils d’autoconfiguration

intégrés

Le Makefile officiel du noyau possède quelques options d’autoconfiguration qui peuvent être utils pour se créer une configuration de base fonctionnel.

defconfig - New config with default from ARCH supplied defconfig

defconfig permet d’utilisé un fichier de configuration « préfabriqué » pour l’architecture de la machine.

À une époque le site kernel-seeds.org (aujourd’hui routé vers le projet Funtoo offrait des fichiers de « seed » customisé. Je n’ai jamais utilisé les fichiers provenant de ce site. Personnellement je pense que je m’en tiendrais au « seeds » officiel des sources du noyau.

localmodconfig - Update current config disabling modules not loaded
localyesconfig - Update current config converting local mods to core

localmodconfig
désactive tous les modules excepté ceux qui sont actuellement utilisé par le système (lsmod).
localyesconfig
fait en sorte que tous les modules soit compilé en dure dans le noyau. Il n’y a donc plus aucun module externe de généré tout est dans l’image vmlinuz.

modprobed-db

modprobed-db est un outils qui permet d’enregistrer la liste des modules utilisés par le système pendant une longue période. Cette outils est destiné à être utilisé avec l’option de configuration localmodconfig pour en améliorer l’efficaté/la pertinance.

AutoKernConf

AutoKernConf permet de détecter le matériel présent (récupérer tous les ID) et de comparer le résultat avec une base de donnée d’ID issue des sources du noyau.

Ce logiciel ne semble plus maintenu mais ça ne veut pas dire qu’il ne fonctionne pas.

Je ne l’ai jamais testé.

première configuration

Pour avoir une première configuration fonctionnel je vous conseil d’utiliser un livecd possédant une version de noyau proche de celui que vous voulez configurer. Dans le répertoire des sources du noyau :

root@server # zcat /proc/config.gz > .config
root@server # make oldconfig
root@server # make localyesconfig
root@server # make menuconfig
root@server # make
…

mise à jour

Nous allons récupéré la configuration du noyau actuelle et l’utiliser comme base pour configurer les sources du nouveau noyau.

Si le noyau actuelle a été configuré avec IKCONFIG_PROC=y on peut récupérer sa configuration dans le fichier /proc/config.gz. Si IKCONFIG_PROC=n mais IKCONFIG=y on peut récupérer la configuration du fichier image sources_noyau/scripts/extract-ikconfig /boot/vmlinuz. Perso j’ai configuré IKCONFIG_PROC=y.

Pour adapter la configuration au nouveau noyau il faut utiliser la target « oldconfig » du Makefile.

oldconfig - Update current config utilising a provided .config as base

Puis « menuconfig » si je veux modifié 23 trucs.

menuconfig - Update current config utilising a menu based program

Pour résumer :

root@server # cd /usr/src/linux
root@server # zcat /proc/config.gz > .config
root@server # make oldconfig
root@server # make menuconfig

compilation

Une fois la configuration terminée on peut compiler est installer le nouveau noyau.

root@server # make
root@server # mount /boot
root@server # mv /boot/vmlinuz /boot/vmlinuz-old
root@server # make image_name
arch/x86/boot/bzImage
root@server # cp arch/x86/boot/bzImage /boot/vmlinuz

On peut remarqué que deux images ont été généré, en fait il s’agit du même fichier.

max@server % find -name bzImage
./arch/i386/boot/bzImage
./arch/x86/boot/bzImage

max@server % namei -l ./arch/i386/boot/bzImage
f: ./arch/i386/boot/bzImage
drwxr-xr-x root root .
drwxr-xr-x root root arch
drwxr-xr-x root root i386
drwxr-xr-x root root boot
lrwxrwxrwx root root bzImage -> ../../x86/boot/bzImage
drwxr-xr-x root root   ..
drwxr-xr-x root root   ..
drwxr-xr-x root root   x86
drwxr-xr-x root root   boot
-rw-r--r-- root root   bzImage

max@server % ll ./arch/i386/boot/bzImage
lrwxrwxrwx 1 root root 22 18 juil. 20:22 ./arch/i386/boot/bzImage -> ../../x86/boot/bzImage

Vous pouvez supprimer l’image du noyau courant dans le dossier /boot sans problème, celui-ci est chargé en mémoire.

modules

Si vous avez choisi de configurer certaines fonctionnalité en tant que modules ceux ci seront compilé lors du build standard.

root@server # make help
…
  all             - Build all targets marked with [*]
* vmlinux         - Build the bare kernel
* modules         - Build all modules
…

Pour les installer vous devrez utiliser la target modules_install. Par défaut il se trouve dans /lib/modules/<version du noyau>.

modules_install - Install all modules to INSTALL_MOD_PATH (default: /)

Une fois que vous avez fait la mise à jour vous devrez supprimer les anciens modules.

root@server # …
root@server # make modules_install

root@server # reboot	

root@server # ls /lib/modules/
3.18.12-gentoo/
4.0.5-gentoo/

root@server # rm -r /lib/modules/3.18.12-gentoo

Attention à ne pas supprimer les modules du noyau courant ! Vous obtiendriez un kernel panic.

firmware

Un « firmware » est un binaire s’executant sur/dans un matériel particulier. Il est normalement contenu dans une mémoire NVRAM du matériel en question. Il ne devrait donc pas être géré par le système d’exploitation.

Certain matériel ne conserve pas leur firmware et nécessite que ceux-ci leur soit envoyé par le driver depuis l’OS.

Dans les sources du noyau on trouve donc un certain nombre de firmware sous forme de blob binaire.

Ils peuvent être stocké sur le système de fichier (dans /lib/firmware) ou en dure dans le noyau.

La target firmware_install permet d’installer les firmware dans /lib/firmware. Tous les firmware sont installé, même ceux utilisé par des modules non compilées.

max@server % make help
…
  firmware_install- Install all firmware to INSTALL_FW_PATH
             (default: $(INSTALL_MOD_PATH)/lib/firmware)
…

La variable de configuration du noyau FIRMWARE_IN_KERNEL permet d’inclure dans le noyau les firmware des modules et fonctionnalité compilées. Ça peut être utils si l’un deux est nécessaire au tout début du boot, lorsque le noyau n’a pas encore accès au système de fichier et que vous n’utilisez pas d’initramfs. En général, ce n’est pas le cas. Je recommande donc de spécifier « FIRMWARE_IN_KERNEL=n » et d’installer les firmware avec make firmware_install.