A propos de initramfs

La seule fonction d'un initramfs est de monter le système de fichier racine. L'initramfs est un ensemble complet de répertoires que vous pouvez trouver dans un système de fichiers racine normal. Il est regroupé dans une seule archive cpio et compressé avec l'un des nombreux algorithmes de compression.

Au moment du démarrage, le chargeur de démarrage charge le noyau et l'image initramfs dans la mémoire et démarre le noyau. Le noyau vérifie la présence d'un initramfs et, s'il le trouve, le monte sur / et lance /init. Le programme init est typiquement un script shell. Notez que le processus de démarrage est plus long, même significativement plus long, si un initramfs est utilisé.

Pour la plus part de distributions, les modules du noyau sont la plus importante raison d'avoir un initramfs. Dans une distribution générale, il y a beaucoup d'inconnues comme les types de systèmes de fichiers et les couches des disques. Dans un sens, c'est l'opposé de LFS où les capacités et les couches du systèmes sont connus et un noyau personnalisé est normallement construit. Dans cette situation, un initramfs est rarement nécessaire.

Il y a seulement quatre raison d'avoir un initramfs dans un environnement LFS : le chargement du rootfs depuis le réseau, son chargement depuis un volume logique LVM, avoir un rootfs chiffré ou un mot de passe est requis, ou pour le confort d'un rootfs spécifié par un LABEL ou un UUID. Les autres cas signifient souvent que le noyau n'est pas configuré correctement.

Construire un initramfs

Si vous décidez de construire un initramfs, les scripts suivants fourniront les bases pour le faire. Les scripts autoriseront la spécification du rootfs via un UUID de partition ou un LABEL de partition ou un rootfs dans un volume logique LVM. Ils ne supportent pas les systèmes de fichier racine chiffrés ou le montage des rootfs par des cartes réseaux. Pour plus d'informations sur les possibilités,voir L'astuce LFS ou dracut.

Pour installer ces scripts, lancez les commandes suivantes en tant qu'utilisateur root :

cat > /sbin/mkinitramfs << "EOF"
#!/bin/bash
# Ce fichier est basé en partie sur le script mkinitrafms pour le LiveCD LFS
# écrit par Alexander E. Patrakov et Jeremy Huntwork.

copy()
{
  local file

  if [ "$2" == "lib" ]; then
    file=$(PATH=/lib:/usr/lib type -p $1)
  else
    file=$(type -p $1)
  fi

  if [ -n $file ] ; then
    cp $file $WDIR/$2
  else
    echo "Missing required file: $1 for directory $2"
    rm -rf $WDIR
    exit 1
  fi
}

if [ -z $1 ] ; then
  INITRAMFS_FILE=initrd.img-no-kmods
else
  KERNEL_VERSION=$1
  INITRAMFS_FILE=initrd.img-$KERNEL_VERSION
fi

if [ -n "$KERNEL_VERSION" ] && [ ! -d "/lib/modules/$1" ] ; then
  echo "No modules directory named $1"
  exit 1
fi

printf "Creating $INITRAMFS_FILE... "

binfiles="sh cat cp dd killall ls mkdir mknod mount "
binfiles="$binfiles umount sed sleep ln rm uname"

sbinfiles="udevadm modprobe blkid switch_root"

#Fichiers et emplacements facultatifs
for f in mdadm udevd; do
  if [ -x /sbin/$f ] ; then sbinfiles="$sbinfiles $f"; fi
done

unsorted=$(mktemp /tmp/unsorted.XXXXXXXXXX)

DATADIR=/usr/share/mkinitramfs
INITIN=init.in

# Création d'un répertoire de travail temporaire
WDIR=$(mktemp -d /tmp/initrd-work.XXXXXXXXXX)

# Création d'une structure de répertoires de base
mkdir -p $WDIR/{bin,dev,lib/firmware,run,sbin,sys,proc}
mkdir -p $WDIR/etc/{modprobe.d,udev/rules.d}
touch $WDIR/etc/modprobe.d/modprobe.conf
ln -s lib $WDIR/lib64

# Création des noeuds de périphériques nécessaires
mknod -m 640 $WDIR/dev/console c 5 1
mknod -m 664 $WDIR/dev/null    c 1 3

# Installation des fichiers de configuration d'udev 
cp /etc/udev/udev.conf $WDIR/etc/udev/udev.conf

for file in $(find /etc/udev/rules.d/ -type f) ; do
  cp $file $WDIR/etc/udev/rules.d
done

# Installation des firmwares présents
cp -a /lib/firmware $WDIR/lib

# Copie du fichier de configuration RAID si présent
if [ -f /etc/mdadm.conf ] ; then
  cp /etc/mdadm.conf $WDIR/etc
fi

# Installer les fichiers de démarrage
install -m0755 $DATADIR/$INITIN $WDIR/init

if [  -n "$KERNEL_VERSION" ] ; then
  if [ -x /bin/kmod ] ; then
    binfiles="$binfiles kmod"
  else
    binfiles="$binfiles lsmod"
    sbinfiles="$sbinfiles insmod"
  fi
fi

# Installer les binaires de base
for f in $binfiles ; do
  ldd /bin/$f | sed "s/\t//" | cut -d " " -f1 >> $unsorted
  copy $f bin
done

# Ajout de lvm si présent
if [ -x /sbin/lvm ] ; then sbinfiles="$sbinfiles lvm"; fi

for f in $sbinfiles ; do
  ldd /sbin/$f | sed "s/\t//" | cut -d " " -f1 >> $unsorted
  copy $f sbin
done

# Ajout de bibliothèques udevd si elles ne sont pas dans /sbin
if [ -x /lib/udev/udevd ] ; then
  ldd /lib/udev/udevd | sed "s/\t//" | cut -d " " -f1 >> $unsorted
fi

# Ajout des liens symboliques des module si c'est adapté
if [ -n "$KERNEL_VERSION" ] && [ -x /bin/kmod ] ; then
  ln -s kmod $WDIR/bin/lsmod
  ln -s kmod $WDIR/bin/insmod
fi

# Ajout des liens symboliques vers lvm si adéquat
if  [ -x /sbin/lvm ] ; then
  ln -s lvm $WDIR/sbin/lvrename
  ln -s lvm $WDIR/sbin/lvextend
  ln -s lvm $WDIR/sbin/lvchange
  ln -s lvm $WDIR/sbin/lvcreate
  ln -s lvm $WDIR/sbin/lvdisplay
  ln -s lvm $WDIR/sbin/lvscan

  ln -s lvm $WDIR/sbin/pvchange
  ln -s lvm $WDIR/sbin/pvck
  ln -s lvm $WDIR/sbin/pvcreate
  ln -s lvm $WDIR/sbin/pvdisplay
  ln -s lvm $WDIR/sbin/pvscan

  ln -s lvm $WDIR/sbin/vgchange
  ln -s lvm $WDIR/sbin/vgcreate
  ln -s lvm $WDIR/sbin/vgscan
  ln -s lvm $WDIR/sbin/vgrename
  ln -s lvm $WDIR/sbin/vgck
fi

# Installation des bibliothèques
sort $unsorted | uniq | while read library ; do
  if [ "$library" == "linux-vdso.so.1" ] ||
     [ "$library" == "linux-gate.so.1" ]; then
    continue
  fi

  copy $library lib
done

cp -a /lib/udev $WDIR/lib

# Installation des modules du noyau si demandé
if [ -n "$KERNEL_VERSION" ]; then
  find                                                                        \
     /lib/modules/$KERNEL_VERSION/kernel/{crypto,fs,lib}                      \
     /lib/modules/$KERNEL_VERSION/kernel/drivers/{block,ata,md,firewire}      \
     /lib/modules/$KERNEL_VERSION/kernel/drivers/{scsi,message,pcmcia,virtio} \
     /lib/modules/$KERNEL_VERSION/kernel/drivers/usb/{host,storage}           \
     -type f 2> /dev/null | cpio --make-directories -p --quiet $WDIR

  cp /lib/modules/$KERNEL_VERSION/modules.{builtin,order}                     \
            $WDIR/lib/modules/$KERNEL_VERSION

  depmod -b $WDIR $KERNEL_VERSION
fi

( cd $WDIR ; find . | cpio -o -H newc --quiet | gzip -9 ) > $INITRAMFS_FILE

# Suppression du répertoire et du fichier temporaires
rm -rf $WDIR $unsorted
printf "done.\n"

EOF
chmod 0755 /sbin/mkinitramfs
mkdir -p /usr/share/mkinitramfs &&
cat > /usr/share/mkinitramfs/init.in << "EOF"
#!/bin/sh

PATH=/bin:/usr/bin:/sbin:/usr/sbin
export PATH

problem()
{
   printf "Probleme rencontre !\n\n Lancement d'un shell.\n\n"
   sh
}

no_device()
{
   printf "Le peripherique %s, qui est suppose contenir le\n" $1
   printf "systeme de fichier root, n'existe pas.\n"
   printf "Veuillez corriger le probleme et quitter ce shell.\n\n"
}

no_mount()
{
   printf "Impossible de monter le peripherique %s\n" $1
   printf "Sommeil eternel. Veuillez rebooter et corriger la ligne de commande du kernel.\n\n"
   printf "Peut-etre le peripherique est formate avec un système de fichier non supporte ?\n\n"
   printf "Ou encoreteme de fichier s'est mal deroulee, dans ce cas\n"
   printf "Vous devriez ajouter le parametre rootfstype=... a la ligne de commande kernel.\n\n"
   printf "Partitions disponibles :\n"
}

do_mount_root()
{
   mkdir /.root
   [ -n "$rootflags" ] && rootflags="$rootflags,"
   rootflags="$rootflags$ro"

   case "$root" in
      /dev/* ) device=$root ;;
      UUID=* ) eval $root; device="/dev/disk/by-uuid/$UUID"  ;;
      LABEL=*) eval $root; device="/dev/disk/by-label/$LABEL" ;;
      ""     ) echo "Pas de racine specifiee." ; problem    ;;
   esac

   while [ ! -b "$device" ] ; do
       no_device $device
       problem
   done

   if ! mount -n -t "$rootfstype" -o "$rootflags" "$device" /.root ; then
       no_mount $device
       cat /proc/partitions
       while true ; do sleep 10000 ; done
   else
       echo "Periherique $root monte avec succes"
   fi
}

init=/sbin/init
root=
rootdelay=
rootfstype=auto
ro="ro"
rootflags=
device=

mount -n -t devtmpfs devtmpfs /dev
mount -n -t proc     proc     /proc
mount -n -t sysfs    sysfs    /sys
mount -n -t tmpfs    tmpfs    /run


read -r cmdline < /proc/cmdline

for param in $cmdline ; do
  case $param in
    init=*      ) init=${param#init=}             ;;
    root=*      ) root=${param#root=}             ;;
    rootdelay=* ) rootdelay=${param#rootdelay=}   ;;
    rootfstype=*) rootfstype=${param#rootfstype=} ;;
    rootflags=* ) rootflags=${param#rootflags=}   ;;
    ro          ) ro="ro"                         ;;
    rw          ) ro="rw"                         ;;
  esac
done

# L'emplacement d'udevd dépend de la version
if [ -x /sbin/udevd ]; then
  UDEV_PATH=/sbin
else
  UDEV_PATH=/lib/udev
fi

${UDEV_PATH}/udevd --daemon --resolve-names=never

udevadm trigger
udevadm settle

if [ -f /etc/mdadm.conf ] ; then mdadm -As                                    ; fi
if [ -x /sbin/vgchange  ] ; then /sbin/vgchange --noudevsync -a y > /dev/null ; fi
if [ -n "$rootdelay"    ] ; then sleep "$rootdelay"                           ; fi

do_mount_root

killall -w ${UDEV_PATH}/udevd

exec switch_root /.root "$init" "$@"

EOF

Utilisation d'un initramfs

Dépendance d'exécution requise

cpio-2.11

Notes d'utilisateur: http://wiki.linuxfromscratch.org/blfs/wiki/initramfs

Pour construire un initramfs, lancer ce qui suit en tant qu'utilisateur root :

mkinitramfs [KERNEL VERSION]

L'argument facultatif est le répertoire ou les modules appropriés du noyau sont enregistrés. Cela peut être un sous-répertoire de /lib/modules. Si aucun modules n'est spécifié, alors l'initramfs est appelé initrd.img-no-kmods. Si une version du noyau est précisé, le fichier initrd est appelé initrd.img-$KERNEL_VERSION et est seulement destiné pour le noyau spécifiquement précisé. Les fichiers de sortie sera enregistré dans le répertoire courrant.

Après avoir généré le fichier initrd, copiez le dans le répertoire /boot.

Maintenant éditez /boot/grub/grub.cfg et ajoutez une nouvelle entrée dans le menu. En dessous, plusieurs exemples sont présentés.

#Initramfs générique et rootfs identifié par UUID
menuentry "LFS Dev (LFS-7.0-Feb14) initrd, Linux 3.0.4"
{
  linux  /vmlinuz-3.0.4-lfs-20120214 root=UUID=54b934a9-302d-415e-ac11-4988408eb0a8 ro
  initrd /initrd.img-no-kmods
}
#Initramfs générique et rootfs sur une partition LVM
menuentry "LFS Dev (LFS-7.0-Feb18) initrd lvm, Linux 3.0.4"
{
  linux  /vmlinuz-3.0.4-lfs-20120218 root=/dev/mapper/myroot ro
  initrd /initrd.img-no-kmods
}
#Initramfs spécifiques et rootfs identifié par un LABEL
menuentry "LFS Dev (LFS-7.1-Feb20) initrd label, Linux 3.2.6"
{
  linux  /vmlinuz-3.2.6-lfs71-120220 root=LABEL=lfs71 ro
  initrd /initrd.img-3.2.6-lfs71-120220
}

Finalement, redémarrez le système et sélectionnez le système désiré.

Last updated on : 2012-09-06 02:03:55 +020