, Johann Schmitz

Ich habe mich ein wenig mit PXE-Boot und initramfs auseinander gesetzt, und ich muss sagen: das macht echt Spass!

Damit ich das nicht wieder vergesse, hier eine Step-by-Step-Anleitung wie man einen Rechner mit einem selbstgebauten Kernel und initramfs per PXE booten lässt:

Kernel-Konfiguration

Diese Konfiguration bezieht sich auf den Kernel der über das Netzwerk geladen und auf dem Client gestartet wird. Der Kernel muss alle Treiber beinhalten, die der Client zum booten und laden des initramfs braucht. Die Treiber müssen dabei einkompiliert werden; Module können zu diesem Zeitpunkt logischerweise noch nicht verwendet werden.

Die einzig wichtige Option in dem Kernel ist:

General Setup
 --> Initial RAM filesystem and RAM disk (initramfs/initrd) support (=y)

Initramfs erstellen

Für das initramfs legen wir uns ein paar Verzeichnisse an:

mkdir /usr/src/initramfs
cd /usr/src/initramfs
mkdir -p bin lib dev etc mnt/root proc root sbin sys

In dieses root-fs kopieren wir jetzt einfach alle Programme die wir in unserer initrd benötigen. Idealerweise baut man die Programme mit +static/+livecd so dass man nur das Executable kopieren muss. Falls das Ebuild das USE-Flag nicht bereitstellt, muss man entweder schauen ob das (hoffentlich vorhandene) configure-Script eine solche Option bereitstellt, oder mittels ldd <executable> herausfinden welche Dateien noch benötigt werden.

Anschliessend müssen wir nur noch das eigentliche Init-Script (PID=1) anlegen. Dieses Script wird nach dem mounten des initramfs gestartet und ist dafür verantwortlich, das neue Root zu mounten und den Init-Prozess an jemand anderen abzugeben.

#!/bin/busybox sh

# Mount the /proc and /sys filesystems.
mount -t proc none /proc
mount -t sysfs none /sys

# Mount the root filesystem.
mount -o ro /dev/sda1 /mnt/root

# Clean up.
umount /proc
umount /sys

# Boot the real thing.
exec switch_root /mnt/root /sbin/init

Das init-Script mountet momentan einfach /dev/sda1 und startet den normalen Init-Prozess. Sicherlich nichts wildes, aber der Fantasie sind da keine Grenzen gesetzt :) Anschliessend noch +x setzen und fertig. Das initramfs-File ist ein gzip-komprimiertes cpio-Archiv. Ein find . -print0 | cpio -ov -0 --format=newc | gzip -9 > /tmp/initramfs.cpio.gz erstellt das passende Archiv.

TFTP-Server konfigurieren

Ich habe hier als TFTP-Server net-ftp/atftp verwendet. In /etc/conf.d/atftp stellt man ein beliebiges Verzeichnis ein, das als Root des TFTP dienen soll. In diese Verzeichnis kopiert man den gebauten Kernel, das initramfs-Image und /usr/share/syslinux/pxelinux.0 (PXE Bootloader aus sys-boot/syslinux). Weiterhin legt man ein Verzeichnix pxelinux.cfg an, das die Configs für die Clients behinhalten wird. Der Bootloader sucht automatisch nach einer Datei mit seiner MAC-Adresse in dem Verzeichnis. Falls er die nicht findet, nimmt der die Datei default. Das ist ganz praktisch, da man so Client-spezifische Konfigurationen anlegen kann.

Die default-Datei beinhaltet folgendes:

prompt 0
timeout 30

label linux
menu label Freaky PXE
kernel bzImage
append initrd=initramfs.cpio.gz vga=0x307

DHCP-Server konfigurieren

Während eines PXE-Boots stellt der Client eine DHCP-Anfrage. Daher müssen wir noch dem DHCP-Server sagen, was er denn einem Client antworten soll. Für dnsmasq gibt man folgendes an:

dhcp-boot=pxelinux.0,,192.168.0.123

Dies weist den Client an von dem Server 192.168.0.123 den Bootloader in pxelinux.0 zu laden.

Durchkicken

Nun kann man den Client neustarten. Wenn man im BIOS das booten vom Netz aktiviert hat, sollte der Rechner nun vom Netz sich das initramfs holen, und danach lokal weiterbooten. Je nachdem was noch in init steht, kann man hier noch die abgefahrensten Sachen machen.

Zum weiterlesen: