Initrd

De wiki.nexiat.fr
Aller à la navigation Aller à la recherche
Fiche express
Domaine Ramdisk initial de boot (montage de la racine)
Fichier /boot/initrd-<version>.img
Outil (RHEL5/6) mkinitrd
Outil (RHEL7+) dracut
Contexte RHEL/CentOS 5 et 6 — remplacé par dracut sur RHEL7+
Voir aussi Kernel · Init

initrd (initial ramdisk) est une image de système de fichiers temporaire, chargée en mémoire par le chargeur de démarrage (GRUB) en même temps que le noyau. Elle embarque les pilotes et modules nécessaires pour monter la vraie racine (/) — typiquement les pilotes de contrôleur disque (RAID, SCSI) ou de carte réseau pour un boot PXE — avant que le noyau ne bascule dessus. Sur RHEL/CentOS 5 et 6, ces images sont générées et modifiées avec mkinitrd ; sur RHEL7 et les distributions récentes, cet outil est remplacé par dracut (voir plus bas), mais le principe reste le même.

Inspecter un initrd existant

Un initrd RHEL5/6 est une archive cpio compressée en gzip ; on peut lister son contenu sans le modifier :

zcat /boot/initrd-$(uname -r).img | cpio -itv

Les modules disponibles pour le noyau en cours se trouvent quant à eux dans /lib/modules/$(uname -r)/kernel/.

Ajouter un module avec mkinitrd

mkinitrd permet de reconstruire un initrd en y intégrant un module supplémentaire, sans avoir à démonter/remonter l'archive à la main. Deux options :

  • --with=<module> : ajoute le module à l'image, chargé si besoin (cas le
 plus courant, ex. un pilote RAID).
  • --preload=<module> : ajoute le module et force son chargement au
 démarrage du système.
cd /boot

# Ajouter le module raid1 (⚠️ toujours écrire vers un nouveau fichier, ne jamais écraser
# l'initrd en place — un système qui ne boote plus est bien plus difficile à corriger)
mkinitrd --with=raid1 initrd-raid1-$(uname -r).img $(uname -r)

# Forcer le chargement d'un module au démarrage (ex. carte RAID matérielle)
mkinitrd --preload=megaraid initrd-megaraid-$(uname -r).img $(uname -r)

Il reste ensuite à déclarer le nouvel initrd dans GRUB (/boot/grub/grub.conf), en dupliquant le bloc de l'entrée de boot existante :

title Red Hat Enterprise Linux ES (2.6.9-42.EL)
        root (hd0,0)
        kernel /vmlinuz-2.6.9-42.EL ro root=/dev/rootvg/lvroot
        initrd /initrd-raid1-2.6.9-42.EL.img

Puis redémarrer sur cette entrée pour valider avant de la rendre permanente.

Ajouter un module manuellement

Utile quand mkinitrd n'est pas disponible (ex. modification d'un initrd d'installation, comme celui du pxeboot d'un CD/DVD Red Hat), ou pour comprendre la structure interne de l'archive. La procédure consiste à :

  1. extraire le contenu de l'initrd ;
  2. ajouter le pilote (fichier .ko ou .o) ;
  3. déclarer le nouveau matériel dans module-info et pcitable ;
  4. reconstruire l'archive.

Extraire l'initrd

# Récupérer initrd.img sur le média d'installation (ex. images/pxeboot/initrd.img du CD/DVD)
mv initrd.img initrd.img.gz
gunzip initrd.img.gz

# Monter le filesystem
mkdir mount-initrd
mount -o loop initrd.img mount-initrd

Les modules sont eux-mêmes dans une seconde archive imbriquée, mount-initrd/modules/modules.cgz, qu'il faut extraire à son tour :

cp mount-initrd/modules/modules.cgz .
mv modules.cgz modules.gz
gunzip modules.gz
cpio -idv < modules

Ajouter le pilote

# Copier le .ko / .o dans le répertoire décompressé (adapter le chemin à l'arch/version)
cp bnx2.o ./2.4.21-37.ELBOOT/i386/

Déclarer le module dans module-info, par exemple pour une carte Broadcom NetXtreme II :

# bnx2
	eth
	"Broadcom NetXtreme II Gigabit Ethernet Driver"

Puis déclarer le(s) identifiant(s) PCI du matériel dans pcitable (à récupérer auprès du constructeur, ou par comparaison avec un pcitable existant via grep bnx2 /usr/share/hwdata/pcitable) :

0x14e4  0x164a  "bnx2"  "Broadcom Corporation|NetXtreme II BCM5706 Gigabit Ethernet"
0x14e4  0x164c  "bnx2"  "Broadcom Corporation|NetXtreme II BCM5708 Gigabit Ethernet"
0x14e4  0x16aa  "bnx2"  "Broadcom Corporation|NetXtreme II BCM5706S Gigabit Ethernet"
0x14e4  0x16ac  "bnx2"  "Broadcom Corporation|NetXtreme II BCM5708S Gigabit Ethernet"

Reconstruire l'archive

# Reconstruire modules.cgz
find ./2.4.21-37.ELBOOT | cpio -ocv > modules
gzip -9 modules
mv modules.gz mount-initrd/modules/modules.cgz

# Démonter et recompresser l'initrd
umount mount-initrd
gzip -9 initrd.img
mv initrd.img.gz initrd.img

Sur les systèmes récents : dracut

Sur RHEL7 et les distributions récentes, mkinitrd est remplacé par dracut, qui régénère l'intégralité de l'initramfs (plutôt que d'y injecter un module à la main) :

# Régénérer l'initramfs du noyau en cours, avec un module supplémentaire
dracut --force --add-drivers raid1 /boot/initramfs-$(uname -r).img $(uname -r)

# Lister le contenu d'un initramfs existant (équivalent de la commande cpio ci-dessus)
lsinitrd /boot/initramfs-$(uname -r).img

⚠️ Comme pour mkinitrd, éviter d'écraser l'image en place avant d'avoir validé le démarrage sur un nouveau fichier déclaré en parallèle dans GRUB.

Voir aussi

  • Kernel — modules et sous-systèmes du noyau chargés depuis l'initrd
  • Init — suite de la séquence de démarrage une fois la vraie racine montée