Eigenen Kernel erstellen

Aus wiki.archlinux.de

Dieser Artikel oder Artikelabschnitt bedarf einer stilistischen Überarbeitung laut Empfehlungen in Artikelstil.


Dieser Artikel wurde als veraltet markiert, und sollte kontrolliert, und gegebenfalls korrigiert bzw. aktualisiert werden.


Hinweis: Nur die ersten beiden großen Überschriften wurden überarbeitet!

In diesem Artikel wird das Erstellen eines eigenen Kernels (Custom-Kernels) beschrieben. Man sollte sich bewusst sein, dass die Funktion des Arch Linux Standard-Kernels garantiert ist, die eines Custom-Kernels nicht. Der von Arch Linux installierte Kernel sollte daher nicht überschrieben werden.

Arten eines eigenen Kernels

Auch bei eigenen Kerneln gibt es verschiedene Wege um an sein Ziel zu kommen. Man kann entweder die von Linus Torvalds und anderen engagierten Programmieren "Vanilla" Packages von https://www.kernel.org herunterladen. Diese Variante wird von vielen Leuten empfohlen, weil man damit den originalen Linux Kernel bekommt. Oder man kann auch die Arch Linux Kernel-Pakete anpassen und damit weitestgehend einen eigenen Kernel erstellen. Seinen wirklich eigenen Kernel bekommt man aber nur, wenn man die erste Variante wählt und die Konfiguration selber übernimmt. Eine Anleitung dazu findet man in dem nächsten "Kapitel".

Ein eigener Kernel auf die normale Art ("Vanilla" Kernel)

Dieser Weg ist der von den Kernelentwicklern empfohlene Weg. Man lädt sich den von den Entwicklern bereitgestellten Code in einem Archiv herunter und entpackt dieses. Danach erzeugt man eine Kernel-Konfiguration und kompiliert schließlich den Kernel. Schließlich erzeugt man ein Initramfs und aktualisiert die Bootloader-Konfiguration, damit der neue Kernel auch erkannt wird und gestartet werden kann.

Vorbereiten

Zuerst muss man allerdings einige Dinge vorbereiten. Das Erstellen eines Kernels auf diese Art und Weise dauert einige Zeit und erfordert etwas Erfahrung. Wenn man das nicht möchte, sollte man in das nächste "Kapitel" schauen.

Herunterladen des Quellcodes

Den Quellcode findet man auf der Seite https://www.kernel.org. Dort findet man auch nicht nur den aktuellen "Stable" Kernel, sondern auch "Long Term" (LTS) und "Mainline" Kernel. In meinem Beispiel nutze ich die Kernelversion 4.16.12. Man kann diesen Kernel mit dem folgendem Befehl herunterladen:

wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.16.12.tar.xz

Die Versionsnummer sollte man seiner Version anpassen. Dies gilt auch für den weiteren Verlauf dieses Artikels.

Vorbereiten des Workspaces

Zuerst muss man den Quellcode auspacken und die entpackten Dateien an einen Ort verschieben, an dem man das Workspace leicht wiederfindet. In meinem Fall werde ich die Dateien nach "/usr/src/" verschieben:

tar xJf linux-4.16.12.tar.xz
sudo mv linux-4.16.12 /usr/src/
cd /usr/src/linux-4.16.12

Danach sollte man zum nächsten Schritt gehen und den Kernel konfigurieren.

Konfigurieren des Kernels

Um festzulegen, welche Teile des Linux Kernels kompiliert werden und ob diese als Modul vorliegen oder direkt in das Kernel Image hineinkompiliert werden, ist es zwingend erforderlich, eine Konfiguration zu erstellen. Es ist egal, ob man dies auf Basis einer alten oder älteren Konfiguration oder auf Basis einer komplett neuen Konfiguration macht. Wichtig ist nur, dass man eine erstellt.
Wenn man die aktuelle Konfiguration auslesen möchte, sind diese Befehle nötig:

zcat /proc/config.gz > .config
make oldconfig

Bei dem letzten Befehl kann es sein, dass man bei bestimmten Funktionen gefragt wird. Hier kann man einfach "ENTER" drücken und die Standardeinstellung nutzen. WICHTIG:
Diese Funktion zum Auslesen der Konfiguration muss vorher im Kernel aktiviert worden sein. Bei dem Arch Linux Standard-Kernel ist dies der Fall.
Möchte man die Konfiguration selber vornehmen, so gibt es verschiedene Möglichkeiten:

Achtung: Man sollte sich mit dem Kernel sehr gut auskennen, da man mit einer eigenen Konfiguration dafür sorgen kann, dass bestimmte elementare Funktionen nicht vorhanden sind! Außerdem kostet die Erstellung einer eigenen Konfiguration viel Zeit und Mühe!

  1. Konsolen-basierte Konfiguration
    Bei dieser Art der Konfiguration wird man wie bei "make oldconfig" für jede Konfiguration gefragt und muss die Antwort angeben oder "ENTER" drücken. Der Befehl lautet:
    make config
  2. Konsolen-basierte Konfiguration mit einfachem Menü
    Bei dieser Art der Konfiguration wird einem ein einfaches Menü in der Konsole angezeigt. Der Befehl lautet:
    make menuconfig
    oder mit nconfig:
    make nconfig
  3. Grafische Konfiguration unter X mit GTK
    Bei dieser Art der Konfiguration wird das Menü aus "make menuconfig" mithilfe von GTK dargestellt. Der Befehl lautet:
    make gconfig
  4. Grafische Konfiguration unter X mit QT
    Bei dieser Art der Konfiguration wird das Fenster nicht mit GTK, sondern mit QT dargestellt. Der Befehl lautet:
    make xconfig

Nach einer fertigen Konfiguration kann mit dem Kompilieren des Kernels begonnen werden.

Kompilieren und Installieren des Kernels

Nachdem man den Kernel konfiguriert hat und gesagt hat, welche Funktionen man haben möchte und welche als Modul ausgelagert werden sollen, muss der Kernel nun kompiliert und installiert werden.

Kompilieren des Kernels

Das Kompilieren des Kernels bedeutet, dass der Quellcode der ausgewählten Teile des Kernels in Maschinensprache übersetzt wird. Dabei werden als Modul markierte Funktionen als Module ausgelagert kompiliert. Andere ausgewählte Funktionen werden zu einer Datei zusammengefasst, die danach nach /boot/ kopiert wird.

Die Kompilierung wird mit dem folgendem Befehl durchgeführt:

make

Die Abarbeitung des Befehls dauert üblicherweise an die zwanzig Minuten.

Tipp: Wenn man nur make ausführt, so wird nur ein Prozessorkern verwendet. Man kann die Compilierzeit mithilfe des Arguments -jX beschleunigen. Das X soll jediglich die Anzahl der CPU-Cores sein. Man kann diese mithilfe von lscpu anzeigen lassen. Wenn man demnach

make -j4

macht, so werden 4 CPU Cores für das Kompilieren miteinbezogen. Man sollte die Anzahl seiner Cores + Threads angeben, da eine zu große Zahl die Geschwindigkeit bremsen anstatt beschleunigen wird.

Beispiel:

Mit einer Quadcore-CPU kann man make -j8 verwenden, da ein Core 2 Threads haben kann.

Installieren des Kernels

Nach dem Kompilieren müssen der Kernel und seine Module installiert werden. Dies geschieht mit den folgenden Befehlen:

sudo cp arch/x86/boot/bzImage /boot/vmlinuz-4.16.12
sudo make modules_install

Nachdem man diese Schritte ausgeführt hat, sollten jetzt die Kernel-Headers angepasst werden.

Einrichten der Kernel-Headers

Hinweis: Die Kernel-Headers sind nicht zwingend erforderlich. Es sei denn, man nutzt DKMS oder bestimmte Treiber!

Die Kernel-Headers befinden sich im Verzeichnis /lib/modules/4.16.12/ bzw. /usr/lib/modules/4.16.12/. Dort sind die Headers aber momentan nicht wirklich installiert. Es wurden nur Verknüpfungen auf die entsprechenden Dateien in dem Workspace angelegt. Deshalb müssen die folgenden Befehle ausgeführt werden:

cd /usr/lib/modules/4.16.12
sudo mv build build.bak
sudo mv source source.bak
sudo mkdir build source
sudo cp -r build.bak/* build/
sudo cp -r source.bak/* source/
sudo rm build.bak
sudo rm source.bak

Damit stehen die Headers für den Kernel jetzt dauerhaft zur Verfügung. Die Headers werden für bestimmte Grafiktreiber und für DKMS gebraucht.

Generieren des Initramfs

Das Initramfs wird benötigt, wenn Funktionen in Module ausgelagert wurden. Es ist dafür da, wichtige Module an dem Anfang des Startvorgangs in den Arbeitsspeicher zu laden. Es wird mit dem folgendem Befehlt generiert:

sudo mkinitcpio -k 4.16.12 -g /boot/initramfs-4.16.12.img

Nachdem der Kernel jetzt fertig installiert und konfiguriert ist, sollte man das Workspace säubern. Danach muss man den Bootloader aktualisieren, damit der Kernel gestartet werden kann.

Säubern des Workspaces

Das Workspace wird mit den folgenden Befehlen gesäubert, wobei ca. 1 GB Speicherplatz frei werden:

cd /usr/src/linux-4.16.12/
make clean

Damit muss nur noch der Bootloader aktualisiert werden, damit der Kernel gestartet werden kann.

Aktualisieren des Bootloaders

Der Bootloader ist für den Start des Kernels zuständig und muss den Kernel erkennen. Dafür ist bei den meisten Bootloadern, wie in meinem Beispiel bei GRUB, ein neu generieren der Konfiguration erforderlich. Wenn man den Bootloader GRUB nutzt, lautet der Befehl:

sudo grub-mkconfig -o /boot/grub/grub.cfg

Wenn man einen anderen Bootloader nutzt, muss man den entsprechenden Befehl nutzen. Der Kernel ist jetzt startbereit und kann getestet werden.

Achtung: Ab hier wurde der Artikel noch nicht weiter überarbeitet! Es wurde nur das Kapitel "Ein angepasster Arch Linux Standardkernel" gelöscht!

Kernel "the arch way"

Ziel ist es, einen eigenen Kernel basierend auf den Sourcen von http://www.kernel.org zu bauen, diesmal aber als Arch-Paket.
Dieses Paket wird über pacman installiert und kann so auch einfach aktualisiert oder entfernt werden.

Diese Methode eignet sich wunderbar um z.B. auch langfristig seinen "eigenen" Kernel mit entsprechenden Konfigurationsanpassungen oder Patches zu pflegen.

Aber auch als Reserve- / Rettungs-Kernel ist diese Methode geeignet, da sich der Rettungskernel wenn nötig sehr einfach an aktuelle Kernel-Quellen anpassen lässt.

Dafür werden wir u.a. eine PKGBUILD Steuerdatei erstellen, die sich prinzipiell an der orientiert, die auch zum Bauen des Arch-Standardkernels verwendet wird.
Der so erstellte Kernel soll einen eigenen Namen bekommen. Für dieses Beispiel anhand des 2.6.22 Kernels soll dieser nachher 2.6.22-custom heißen.

Zum Bauen erstellen wir ein eigenes Verzeichnis, hier als Beispiel im Home-Verzeichnis.

 mkdir ~/kernel26-custom
 cd ~/kernel26-custom

Jetzt erstellen wir uns die notwendigen Steuerdateien um das Paket mit makepkg bauen zu können. Im Gegensatz zur Methode 2 (Arch-Standard-Kernel anpassen) sind nachfolgend diese Dateien komplett aufgeführt. Diese müssen also lediglich aus dem Wiki rauskopiert werden.

PKGBUILD

# Contributor: Your name

pkgname=kernel26custom
basekernel=2.6.22
pkgver=2.6.22
_ownver=custom
pkgrel=1
pkgdesc="The Linux Kernel and modules  (Eigener Kernel)"
url=""
license="GPL"
arch=(i686 x86_64)
depends=('module-init-tools' 'mkinitcpio>=0.5.15')
install=${pkgname}.install
source=(ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-${basekernel}.tar.bz2 \
        ${pkgname}.preset \
        ${pkgname}-fallback.conf \
        )
build() {
  [ "${CARCH}" = "i686" ]   && KARCH=i386
  [ "${CARCH}" = "x86_64" ] && KARCH=x86_64

  cd $startdir/src/linux-${basekernel}

  # Enable this to reuse your old kernel config.
  # The config file must sit in the directory where the PKGBUILD is.
  # Also enable: make oldconfig in the section below.
  cp $startdir/config ./.config

  # load configuration
  #yes "" | make config
  make oldconfig || return 1
  make menuconfig || return 1
  #make gconfig || return 1
  . ./.config
  _kernver="${basekernel}${CONFIG_LOCALVERSION}"

  # build!
  make bzImage modules || return 1
  mkdir -p $startdir/pkg/{lib/modules,boot}
  make INSTALL_MOD_PATH=$startdir/pkg modules_install || return 1
  cp System.map $startdir/pkg/boot/System.map26${_ownver}
  cp arch/$KARCH/boot/bzImage $startdir/pkg/boot/vmlinuz26${_ownver}
  install -D -m644 Makefile \
    $startdir/pkg/usr/src/linux-${_kernver}/Makefile
  install -D -m644 kernel/Makefile \
    $startdir/pkg/usr/src/linux-${_kernver}/kernel/Makefile
  install -D -m644 .config \
    $startdir/pkg/usr/src/linux-${_kernver}/.config
  install -D -m644 .config $startdir/pkg/boot/kconfig26${_ownver}
  mkdir -p $startdir/pkg/usr/src/linux-${_kernver}/include

  mkdir -p $startdir/pkg/usr/src/linux-${_kernver}/arch/$KARCH/kernel
  for i in acpi asm-generic asm-$KARCH config linux math-emu media net pcmcia scsi sound video; do
    cp -a include/$i $startdir/pkg/usr/src/linux-${_kernver}/include/
  done

 # copy files necessary for later builds, like nvidia and vmware
  cp Module.symvers $startdir/pkg/usr/src/linux-${_kernver}
  cp -a scripts $startdir/pkg/usr/src/linux-${_kernver}
  # fix permissions on scripts dir
  chmod og-w -R $startdir/pkg/usr/src/linux-${_kernver}/scripts
  mkdir -p $startdir/pkg/usr/src/linux-${_kernver}/.tmp_versions

  cp arch/$KARCH/Makefile $startdir/pkg/usr/src/linux-${_kernver}/arch/$KARCH/
  if [ "$CARCH" = "i686" ]; then
    cp arch/$KARCH/Makefile.cpu $startdir/pkg/usr/src/linux-${_kernver}/arch/$KARCH/
  fi
  cp arch/$KARCH/kernel/asm-offsets.s $startdir/pkg/usr/src/linux-${_kernver}/arch/$KARCH/kernel/

  # add headers for lirc package
  mkdir -p $startdir/pkg/usr/src/linux-${_kernver}/drivers/media/video
  cp drivers/media/video/*.h  $startdir/pkg/usr/src/linux-${_kernver}/drivers/media/video/
  for i in bt8xx cpia2 cx25840 cx88 em28xx et61x251 pwc saa7134 sn9c102 usbvideo zc0301; do
   mkdir -p $startdir/pkg/usr/src/linux-${_kernver}/drivers/media/video/$i
   cp -a drivers/media/video/$i/*.h $startdir/pkg/usr/src/linux-${_kernver}/drivers/media/video/$i
  done
  # add dm headers
  mkdir -p $startdir/pkg/usr/src/linux-${_kernver}/drivers/md
  cp drivers/md/*.h  $startdir/pkg/usr/src/linux-${_kernver}/drivers/md
  # add inotify.h
  mkdir -p $startdir/pkg/usr/src/linux-${_kernver}/include/linux
  cp include/linux/inotify.h $startdir/pkg/usr/src/linux-${_kernver}/include/linux/
  # add CLUSTERIP file for iptables
  mkdir -p $startdir/pkg/usr/src/linux-${_kernver}/net/ipv4/netfilter/
  cp net/ipv4/netfilter/ipt_CLUSTERIP.c $startdir/pkg/usr/src/linux-${_kernver}/net/ipv4/netfilter/
  # copy in Kconfig files
  for i in `find . -name "Kconfig*"`; do
    mkdir -p $startdir/pkg/usr/src/linux-${_kernver}/`echo $i | sed 's|/Kconfig.*||'`
    cp $i $startdir/pkg/usr/src/linux-${_kernver}/$i
  done

  if [ "${KARCH}" = "i386" ]; then
    mkdir ${startdir}/pkg/usr/src/linux-${_kernver}/include/asm-x86_64
    cp -a include/asm-x86_64/tsc.h ${startdir}/pkg/usr/src/linux-${_kernver}/include/asm-x86_64
  else
    mkdir ${startdir}/pkg/usr/src/linux-${_kernver}/include/asm-i386
    cp -a include/asm-i386/{tsc,msr-index,processor-flags}.h ${startdir}/pkg/usr/src/linux-${_kernver}/include/asm-i386
  fi

  cd $startdir/pkg/usr/src/linux-${_kernver}/include && ln -s asm-$KARCH asm

  chown -R root.root $startdir/pkg/usr/src/linux-${_kernver}
  find $startdir/pkg/usr/src/linux-${_kernver} -type d -exec chmod 755 {} \;
  cd $startdir/pkg/lib/modules/${_kernver} && \
    (rm -f source build; ln -sf ../../../usr/src/linux-${_kernver} build)
  # for binary modules make prepare
  # cd $startdir/pkg/lib/modules/${_kernver}/build
  # make prepare
  # install fallback mkinitcpio.conf and kernel preset files
  install -m644 -D $startdir/src/kernel26custom.preset $startdir/pkg/etc/mkinitcpio.d/kernel26custom.preset
  install -m644 -D $startdir/src/kernel26custom-fallback.conf $startdir/pkg/etc/mkinitcpio.d/kernel26custom-fallback.conf
  # set correct depmod command for install
  sed -i -e "s/KERNEL_VERSION=.*/KERNEL_VERSION=${_kernver}/g" $startdir/kernel26${_ownver}.install
  echo -e "# NEVER EDIT THIS FILE\nALL_kver='${_kernver}'" > ${startdir}/pkg/etc/mkinitcpio.d/${pkgname}.kver

  # Copy the current - maybe changed - kernel config back to our startdir.
  # This is for easier reuse of this good config on the next run.
  cp $startdir/src/linux-${basekernel}/.config $startdir/config
}

kernel26custom.install

# arg 1:  the new package version
# arg 2:  the old package version

# Change this if either your kernel version or your local version changed
KERNEL_VERSION=2.6.22-custom
_ownver=custom

post_install () {
  # updating module dependencies
  echo ">>> Updating module dependencies. Please wait ..."
  depmod -v $KERNEL_VERSION > /dev/null 2>&1
  # generate init ramdisks
  echo ">>> MKINITCPIO SETUP"
  echo ">>> ----------------"
  echo ">>> If you use LVM2, Encrypted root or software RAID,"
  echo ">>> Ensure you enable support in /etc/mkinitcpio.conf ."
  echo ">>> More information about mkinitcpio setup can be found here:"
  echo ">>> http://wiki.archlinux.org/index.php/Mkinitcpio"
  echo ""
  echo ">>> Generating initial ramdisk, using mkinitcpio.  Please wait..."
if [ "`vercmp $2 2.6.19`" -lt 0 ]; then
  /sbin/mkinitcpio -p kernel26${_ownver} -m "ATTENTION:\nIf you get a kernel panic below
and are using an Intel chipset, append 'earlymodules=piix' to the
kernel commandline"
else
  /sbin/mkinitcpio -p kernel26${_ownver}
fi
if [ "`vercmp $2 2.6.21`" -lt 0 ]; then
  echo ""
  echo "Important ACPI Information:"
  echo ">>> Since 2.6.20.7 all possible ACPI parts are modularized."
  echo ">>> The modules are located at:"
  echo ">>> /lib/modules/$(uname -r)/kernel/drivers/acpi"
  echo ">>> For more information about ACPI modules check this wiki page:"
  echo ">>> 'http://wiki.archlinux.org/index.php/ACPI_modules'"
fi
}

post_upgrade() {
  pacman -Q grub &>/dev/null
  hasgrub=$?
  pacman -Q lilo &>/dev/null
  haslilo=$?
  # reminder notices
  if [ $haslilo -eq 0 ]; then
    echo ">>>"
    if [ $hasgrub -eq 0 ]; then
      echo ">>> If you use the LILO bootloader, you should run 'lilo' before rebooting."
    else
      echo ">>> You appear to be using the LILO bootloader. You should run"
      echo ">>> 'lilo' before rebooting."
    fi
    echo ">>>"
  fi

  if grep "/boot" /etc/fstab 2>&1 >/dev/null; then
    if ! grep "/boot" /etc/mtab 2>&1 >/dev/null; then
      echo "WARNING: /boot appears to be a seperate partition but is not mounted"
      echo "         This is most likely not what you want.  Please mount your /boot"
      echo "         partition and reinstall the kernel unless you are sure this is OK"
    fi
  fi

  if [ "`vercmp $2 2.6.13`" -lt 0 ]; then
    # important upgrade notice
    echo ">>>"
    echo ">>> IMPORTANT KERNEL UPGRADE NOTICE"
    echo ">>> -------------------------------"
    echo ">>> As of kernel 2.6.13, DevFS is NO LONGER AVAILABLE!"
    echo ">>> If you still use DevFS, please make the transition to uDev before"
    echo ">>> rebooting.  If you really need to stay with DevFS for some reason,"
    echo ">>> then you can manually downgrade to an older version:"
    echo ">>>"
    echo ">>> # pacman -U http://archlinux.org/~judd/kernel/kernel26-scsi-2.6.12.2-1.pkg.tar.gz"
    echo ">>>"
    echo ">>> If you choose to downgrade, don't forget to add kernel26-scsi to your"
    echo ">>> IgnorePkg list in /etc/pacman.conf"
    echo ">>>"
    echo ">>> (NOTE: The following portion applies to uDev users as well!)"
    echo ">>>"
    echo ">>> If you use any DevFS paths in your GRUB menu.lst, then you will not"
    echo ">>> be able to boot!  Change your root= parameter to use the classic"
    echo ">>> naming scheme."
    echo ">>>"
    echo ">>> EXAMPLES:"
    echo ">>> - change root=/dev/discs/disc0/part3 to root=/dev/sda3"
    echo ">>> - change root=/dev/md/0 to root=/dev/md0"
    echo ">>>"
  fi
 # generate new init ramdisk
  if [ "`vercmp $2 2.6.18`" -lt 0 ]; then
    echo ">>> --------------------------------------------------------------"
    echo ">>> |                          WARNING:                          |"
    echo ">>> |mkinitrd is not supported anymore in kernel >=2.6.18 series!|"
    echo ">>> |              Please change to Mkinitcpio setup.            |"
    echo ">>> --------------------------------------------------------------"
    echo ">>>"
  fi
  # updating module dependencies
  echo ">>> Updating module dependencies. Please wait ..."
  depmod -v $KERNEL_VERSION > /dev/null 2>&1
  echo ">>> MKINITCPIO SETUP"
  echo ">>> ----------------"
  if [ "`vercmp $2 2.6.18`" -lt 0 ]; then
    echo ">>> Please change your bootloader config files:"
    echo ">>> Grub: /boot/grub/menu.lst | Lilo: /etc/lilo.conf"
    echo "------------------------------------------------"
    echo "| - initrd26.img to kernel26.img               |"
    echo "| - initrd26-full.img to kernel26-fallback.img |"
    echo "------------------------------------------------"
  fi
  if [ "`vercmp $2 2.6.19`" -lt 0 ]; then
    echo ""
    echo ">>> New PATA/IDE subsystem - EXPERIMENTAL"
    echo ">>> ----------"
    echo ">>> To use the new pata drivers, change the 'ide' hook "
    echo ">>> to 'pata' in /etc/mkinicpio.conf HOOKS="
    echo ">>> The new system changes: /dev/hd? to /dev/sd?"
    echo ">>> Don't forget to modify GRUB, LILO and fstab to the"
    echo ">>> new naming system. "
    echo ">>> eg: hda3 --> sda3, hdc8 --> sdc8"
    echo ""
    echo ">>> piix/ata_piix (Intel chipsets) - IMPORTANT"
    echo "----------"
    echo ">>> If you have enabled ide/pata/sata HOOKs in /etc/mkinitcpio.conf"
    echo ">>> the 'ata_piix' module will be used."
    echo ">>> This may cause your devices to shift names, eg:"
    echo ">>> - IDE: devices from hd? to sd?"
    echo ">>> - SATA: sda might shift to sdc if you have 2 other disks on a PIIX IDE port."
    echo ">>> To check if this will affect you, check 'mkinitcpio -M' for piix/ata_piix"
    echo ""
  fi

  echo ">>> If you use LVM2, Encrypted root or software RAID,"
  echo ">>> Ensure you enable support in /etc/mkinitcpio.conf ."
  echo ">>> More information about mkinitcpio setup can be found here:"
  echo ">>> http://wiki.archlinux.org/index.php/Mkinitcpio"
  echo ""
  echo ">>> Generating initial ramdisk, using mkinitcpio.  Please wait..."
if [ "`vercmp $2 2.6.19`" -lt 0 ]; then
  /sbin/mkinitcpio -p kernel26${_ownver} -m "ATTENTION:\nIf you get a kernel panic below
and are using an Intel chipset, append 'earlymodules=piix' to the
kernel commandline"
else
  /sbin/mkinitcpio -p kernel26${_ownver}
fi
if [ "`vercmp $2 2.6.21`" -lt 0 ]; then
  echo ""
  echo "Important ACPI Information:"
  echo ">>> Since 2.6.20.7 all possible ACPI parts are modularized."
  echo ">>> The modules are located at:"
  echo ">>> /lib/modules/$(uname -r)/kernel/drivers/acpi"
  echo ">>> For more information about ACPI modules check this wiki page:"
  echo ">>> 'http://wiki.archlinux.org/index.php/ACPI_modules'"
fi
}

op=$1
shift

$op $*

kernel26custom.conf

# vim:set ft=sh
# MODULES
# The following modules are loaded before any boot hooks are
# run.  Advanced users may wish to specify all system modules
# in this array.  For instance:
#     MODULES="piix ide_disk reiserfs"
# BusLogic is added to support VMWARE arch booting in fallback image
MODULES="BusLogic"

# BINARIES
# This setting includes, into the CPIO image, and additional
# binaries a given user may wish.  This is run first, so may
# be used to override the actual binaries used in a given hook.
# (Existing files are NOT overwritten is already added)
# BINARIES are dependancy parsed, so you may safely ignore libraries
#BINARIES=""

# FILES
# This setting is similar to BINARIES above, however, files are added
# as-is and are not parsed in anyway.  This is useful for config files.
# Some users may wish to include modprobe.conf for custom module options,
# like so:
#    FILES="/etc/modprobe.d/modprobe.conf"
FILES=""

# HOOKS
# This is the most important setting in this file.  The HOOKS control the
# modules and scripts added to the image, and what happens at boot time.
# Order is important, and it is recommended that you do not change the
# order in which HOOKS are added.  Run 'mkinitcpio -H <hook name>' for
# help on a given hook.
# 'base' is _required_ unless you know precisely what you are doing.
# 'udev' is _required_ in order to automatically load modules
# 'modload' may be used in place of 'udev', but is not recommended
# 'filesystems' is _required_ unless you specify your fs modules in MODULES
# Examples:
#    This setup specifies all modules in the MODULES setting above.
#    No raid, lvm, or encrypted root is needed.
#    HOOKS="base"
#
#    This setup will autodetect all modules for your system and should
#    work as a sane default
#    HOOKS="base udev autodetect ide scsi sata filesystems"
#
#    This setup will generate a 'full' image which supports most systems.
#    No autodetection is done.
#    HOOKS="base udev ide scsi sata usb filesystems"
#
#    This setup assembles an ide raid array with an encrypted root FS.
#    Note: See 'mkinitcpio -H raid' for more information on raid devices.
#    HOOKS="base udev ide filesystems raid encrypt"
#
#    This setup loads an LVM volume group on a usb device.
#    HOOKS="base udev usb filesystems lvm"
HOOKS="base udev ide scsi sata usbinput raid filesystems"

kernel26custom-fallback.conf

# vim:set ft=sh
# MODULES
# The following modules are loaded before any boot hooks are
# run.  Advanced users may wish to specify all system modules
# in this array.  For instance:
#     MODULES="piix ide_disk reiserfs"
# BusLogic is added to support VMWARE arch booting in fallback image
MODULES="BusLogic"

# BINARIES
# This setting includes, into the CPIO image, and additional
# binaries a given user may wish.  This is run first, so may
# be used to override the actual binaries used in a given hook.
# (Existing files are NOT overwritten is already added)
# BINARIES are dependancy parsed, so you may safely ignore libraries
#BINARIES=""

# FILES
# This setting is similar to BINARIES above, however, files are added
# as-is and are not parsed in anyway.  This is useful for config files.
# Some users may wish to include modprobe.conf for custom module options,
# like so:
#    FILES="/etc/modprobe.d/modprobe.conf"
FILES=""

# HOOKS
# This is the most important setting in this file.  The HOOKS control the
# modules and scripts added to the image, and what happens at boot time.
# Order is important, and it is recommended that you do not change the
# order in which HOOKS are added.  Run 'mkinitcpio -H <hook name>' for
# help on a given hook.
# 'base' is _required_ unless you know precisely what you are doing.
# 'udev' is _required_ in order to automatically load modules
# 'modload' may be used in place of 'udev', but is not recommended
# 'filesystems' is _required_ unless you specify your fs modules in MODULES
# Examples:
#    This setup specifies all modules in the MODULES setting above.
#    No raid, lvm, or encrypted root is needed.
#    HOOKS="base"
#
#    This setup will autodetect all modules for your system and should
#    work as a sane default
#    HOOKS="base udev autodetect ide scsi sata filesystems"
#
#    This setup will generate a 'full' image which supports most systems.
#    No autodetection is done.
#    HOOKS="base udev ide scsi sata usb filesystems"
#
#    This setup assembles an ide raid array with an encrypted root FS.
#    Note: See 'mkinitcpio -H raid' for more information on raid devices.
#    HOOKS="base udev ide filesystems raid encrypt"
#
#    This setup loads an LVM volume group on a usb device.
#    HOOKS="base udev usb filesystems lvm"
HOOKS="base udev ide scsi sata usbinput raid filesystems"

kernel26custom.preset

# mkinitcpio preset file for kernel26custom

########################################
# NEVER EDIT THIS LINE:
source /etc/mkinitcpio.d/kernel26custom.kver
########################################

PRESETS=('default' 'fallback')

default_config="/etc/mkinitcpio.conf"
default_image="/boot/kernel26custom.img"

fallback_config="/etc/mkinitcpio.d/kernel26custom-fallback.conf"
fallback_image="/boot/kernel26custom-fallback.img" 

Build-Prozess vorbereiten, Prüfsummen erzeugen
Dieser Vorgang muss jedesmal ausgeführt werden, wenn sich eine Datei ändert die im PKGBUILD unter source=(...) aufgeführt ist. Die alten Prüfsummen in PKGBUILD sind vorher zu löschen.

makepkg -g >> PKGBUILD 

Ein wichtiger Punkt ist die Kernel-Konfigurationsdatei. Wir haben hier (wenn dieser Vorgang zum ersten Mal ausgeführt wird) folgende Möglichkeiten:
1. Wir können die Konfiguration des momentanen Kernel (wahrscheinlich der Arch-Standard-Kernel) als Vorlage nehmen. Das beschert uns die gleichen Treiber/Module wie sie dieser Kernel mitbringt. Allerdings können wir während des Build-Prozesses diese Konfig abändern um z.B. Treiber für nicht vorhandene Hardware wegzulassen. Dazu ist aber etwas an Erfahrung notwendig.
Wir bekommen diese Konfig, indem wir die momentane in unser Verzeichnis kopieren:

 zcat /proc/config.gz > ./config

2. Ganz erfahrene User können sich die Konfig quasi von Null selbst einstellen
Dafür darf keine Konfig-Datei config im Verzeichnis mit der PKGBUILD vorhanden sein. Beim erstmaligen Start ist auch keine vorhanden.

Während des Build-Prozesses wird diese Ausgangs-Konfig verwendet um daraus eine zum bauenden Kernel passende Konfig zu erstellen. Dies geschieht durch den Aufruf von make oldconfig im Ablauf der PKGBUILD.
Danach wird basierend auf dieser Konfig ein Frontend zum Editieren gestartet. In obiger PKGBUILD ist das make menuconfig. Mit diesem Frontend kann die Konfiguration angepasst werden.

Ganz wichtig: Im Zuge der Konfiguration mit dem Frontend muss unbedingt die lokale Version unserer Konfig eingestellt werden!
Zu finden ist dieser Parameter unter General setup->Local Version. Hier muss unserer lokaler Zusatz eingetragen werden, in diesem Fall -custom.

Build-Prozess starten

makepkg -c

Das Frontend zur Kernel-Konfig nach der oben beschriebenen Bearbeitung beenden und die Konfiguration speichern lassen. Danach wird der Build-Prozess normal weitergeführt.
Wenn alles glatt gelaufen ist, dann sehen wir eine ähnliche Meldung wie diese auf dem Bildschirm:

 ==> Compressing package...
 ==> Finished making: kernel26custom  (Wed Aug 15 08:59:23 CEST 2007)

Wir erhalten auch unser Kernel-Paket, welches über pacman installiert wird

kernel26custom-2.6.22-1-i686.pkg.tar.gz

Die Installation läuft entsprechend der normaler Kernel-Installation, wie wir sie kennen, ab.

pacman -U kernel26custom-2.6.22-1-i686.pkg.tar.gz

Eine Besonderheit ist hier noch zu erwähnen: Wenn der Build-Vorgang erfolgreich war, dann hat das PKGBUILD-Skript die von Dir eventuell angepasste Kernel-Konfigdatei zurück ins "Startverzeichnis" kopiert.
Warum? Damit der nächste Lauf immer mit deiner guten, aktuellen Konfiguration startet.

Bootloader anpassen
Jetzt fehlt lediglich noch der Eintrag im Bootloader (Grub) für unseren neuen Kernel. Die Einträge zu root und root= analog der eigenen menu.list anpassen!

# Eigener Kernel 2
title  Eigener Kernel (custom)
root   (hd0,0)
kernel /vmlinuz26custom root=/dev/sda3 ro
initrd /kernel26custom.img

# (1) Arch Linux
title  Eigener Kernel (custom) Fallback
root   (hd0,0)
kernel /vmlinuz26custom root=/dev/sda3 ro
initrd /kernel26custom-fallback.img

Hat sich dieser Aufwand jetzt gelohnt?
Der Vorteil dieser Methode kommt eigentlich erst richtig zum tragen, wenn wir z.B. eine Änderung an diesem Kernel vornehmen wollen. Sei es, dass wir eine andere Version der Vanilla-Kernelsourcen einbinden wollen, oder lediglich an der Konfig etwas verändern möchten.

Angenommen, du müsstest die Konfig verändern. Dann würde das Prozedere so ablaufen:

  • Prüfsummen (md5sums=) aus der PKGBUILD löschen
  • In der PKGBUILD den Wert von pkgrel um 1 erhöhen
  • makepkg -g >> PKGBUILD
  • makepkg
  • pacman -U kernel26custom-2.6.22-2-i686.pkg.tar.gz

Und schon wäre unser Kernel aktualisiert

Was ist mit den externen Treibern? Z.B. Nvidia?

Um diese unter dem Reserve/Notfall-Kernel bzw. unter einem ständigen eigenen Paket installieren und nutzen zu können müssen diese Pakete auch selbst kompiliert werden. Eben passend zu unserem Kernel.

Diese Pakete kommen entweder aus dem ABS oder dem AUR. Das Prinzip funktioniert wie bei unserem Kernel: wir editieren die PKGBUILD's und andere Steuerdateien und passen diese an unsere Kernel-Version/Namen an.

Exemplarisch z.B. für den aktuellen NVidia-Treiber:
ABS aktualisieren

abs

Das PKGBUILD kopieren

cp -R /var/abs/extra/x11/nvidia /var/abs/local/
cd /var/abs/local
mv nvidia nvidia-custom
cd nvidia-custom

Dateien editieren Der Einfachheit halber hier nur die Änderungen:
PKGBUILD
pkgname=nvidia-custom
_kernver='2.6.22-custom'
pkgrel=1
pkgdesc="NVIDIA drivers for kernel26custom."
depends=('kernel26custom' 'nvidia-utils')
nvidia-install
KERNEL_VERSION='2.6.22-custom'
post_remove() {
KERNEL_VERSION='2.6.22-custom'

Paket bauen

makepkg

Installieren

pacman -U nvidia-custom-100.14.11-1-i686.pkg.tar.gz

Analog ist mit anderen, externen Kernel-Modulen zu verfahren.

Welche Parameter bewirken Namensänderungen?

Es gibt bei den vorgestellten Verfahren mehrere Parameter in verschiedenen Configs, die später eine Auswirkung darauf haben:

  • wie der Kernel "heißt" (uname -r)
  • wie das Verzeichnis heißt, in dem die Module installiert werden (/lib/modules/$name)
  • wie das ArchLinux-Paket heißt (unser Paket darf im Paketsystem z.B. nicht mit dem Paket kernel26 kollidieren)

.config
Die Kernel-Config, die wir z.B. mit make menuconfig erstellen oder die beim Arch-Standard-Kernel analog obigen Beispielen in $HOME/kernel26-custom als config bzw. config.x86_64 liegt.

#
# General setup
#
CONFIG_LOCALVERSION="-custom"

Was wir hier eintragen wird intern an den Kernel-Namen angehängt und bewirkt u.a. auch, wie das Modul-Verzeichnis heißt. Wenn wir CONFIG_LOCALVERSION="-custom" eintragen, dann wird der Kernel die Module in /lib/modules/2.6.22-custom suchen.

PKGBUILD
Wenn wir einen Kernel mit dem Paketmanagement bauen, dann haben Parameter darin Auswirkungen wie später das gebaute Paket heißt und welchen Namen der Kernel in der Paketdatenbank hat. Dies müssen wir anpassen um nicht mit den Standard-Kerneln zu kollidieren.

 pkgname=kernel26custom

Dies bewirkt, wie das Paket zum Installieren heißt (blabla.pkg.tar.gz), welchen Namen Verzeichnisse und Kernel bzw. initrd-Image haben.

 _ownver=custom

Dies ist ein eigener Parameter, den wir benutzen um in der Steuerdatei unseren Versionszusatz an z.B. Kopieraktionen anzuhängen.

 pkgrel=1

Wenn wir unseren eigenen Kernel später mal verändern, dann sollten wir diesen Parameter um Eins erhöhen. Dadurch können wir mit pacman unser Paket leicht aktualisieren.