QVINTVS · SCRIBET

Arch Linux mit UEFI auf einem Thinkpad E330

Bisher habe ich mich um UEFI immer gedrückt und einen Legacy-Boot durchgeführt. Es war aber von vornherein klar, dass es sich dabei um keinen Dauerzustand handeln konnte, sodass ich mich nunmehr der Problematik von UEFI angenommen habe. Nicht wirklich erleichtert wurde dies durch einen Bug in der Firmware des Laptops, der einen Boot mittels Kernel-eigenem EFISTUB verhindert.GPT kennt keine „erweiterte Partition“, da die Begrenzung auf vier primäre Partitionen entfallen ist.

Bei UEFI (Unified Extensible Firmware Interface) handelt es sich um den Nachfolger des angestammten BIOS (Basic Input/Output System). Ohne auf eine nähere Betrachtung der Vor- und Nachteile einzugehen, genügt es zu sagen, dass BIOS völlig veraltet und demzufolge stark limitiert ist und ein Nachfolger dringend erforderlich war, der sich nun eben in UEFI gefunden hat. Die verhältnismäßig junge Technologie macht (wohl aufgrund ihrer Hardwarenähe) dem ein oder anderen Hardwarehersteller noch Probleme, sodass das eigentlich sehr einfache Booten mit UEFI zu einer Tagesaufgabe wird, wenn man nicht Microsoft Windows booten will. So auch bei Lenovo, dem Hersteller der Thinkpads. Doch dazu sogleich.

Einstieg

Zunächst ist ein Arch-Linux-Live-System auf einem USB-Stick erforderlich. Die ISO kann einfach von der Website heruntergeladen und anschließend auf einen USB-Stick geschrieben werden:

# dd if=archlinux-2014.02.01-dual.iso of=/dev/sdb bs=1M
# sync

Die Archlinux-ISO verwendet einige Tricks, um sowohl als MBR als auch als GPT erkannt zu werden, die uns an dieser Stelle allerdings nicht weiter interessieren sollen. Es genügt, dass auf einem normalen UEFI-System das Live-System auch per UEFI gebootet wird. Normalerweise.

Lenovo

Diese ganze Anleitung wäre überflüssig, wenn alles so funktionieren würde wie gewünscht. Leider ist dem nicht so. Lenovo (und evtl. auch weitere Hersteller) hat nämlich einen schwer greifbaren, dafür aber umso fataleren Bug in seiner UEFI-Firmware eingebaut. In den Arch-Linux-Foren wurde intensiv darüber diskutiert, jedoch keine abschließende Lösung gefunden: Die Lenovo-Firmware macht es unmöglich, gewisse Kernelversionen via EFISTUB, dem eingebauten Bootloader von Linux, zu booten.

Bootloader?

Der UEFI-Boot läuft über zwei Stufen: Ein Bootmanager, der den Nutzer auswählen lässt, was zu booten ist und ein nachgeschalteter Bootloader, der den eigentlichen Bootvorgang durchführt. Die Firmware des Hardwareherstellers bietet einen rudimentären Bootmanager an, der auf die im jeweiligen Betriebssystemkernel verfügbare Bootloaderfunktion zurückgreift (bei Linux eben EFISTUB). Da der eingebaute Bootmanager meist sperrig und featurearm ist, haben sich zahlreiche Alternativen gebildet: rEFInd und gummiboot etwa. Alle diese leichtgewichtigen Bootmanager haben jedoch eines gemeinsam: Sie booten via EFISTUB. Da auch die Archlinux-ISO Gummiboot verwendet, heißt das für mein Lenovo-Laptop: Ich kann das Arch-Livesystem nicht booten. Gummiboot startet noch und ich kann zwischen dem Arch-Livesystem und einer UEFI-Shell wählen, jedoch endet der Start des Arch-Live-Systems in einem schwarzen Bild. Nichts passiert. Die UEFI-Shell dagegen startet (zum Glück, wir werden sie noch brauchen).

Die einzige Möglichkeit, Arch Linux zu installieren geht daher erstmal über den Legacy-Modus der Firmware. Dazu den Bootprozess per Return-Taste unterbrechen und mit F1 ins Setup wechseln. Dort unter „Boot“ den Eintrag „UEFI boot“ auf „Legacy Only“ ändern. Um der ganz eigenen Problematik der UEFI-Erweiterung Secure Boot zuvorzukommen, sollte unter „Security“ die betreffende Einstellung von vornherein deaktiviert werden. Die Änderungen speichern und das Setup verlassen und den Computer ausschalten. Das USB-Medium unterstützt wie beschrieben sowohl den MBR- als auch den UEFI-Modus, sodass bei neuerlichem Anschalten, Unterbrechen mit Return und anwählen des USB-Sticks per F12 nun auch eine Arch-Linux-Option zur Verfügung stehen sollte, die auch wirklich bootfähig ist. Grundsätzlich kann nun der Installationsanleitung gefolgt werden, jedoch müssen insbesondere bei der Partitionierung ein paar Sachen beachtet werden.

Die neue Partitionstabelle

Zusammen mit BIOS wurde die klassische MSDOS/MBR-Partitionstabelle abgelöst. Zwar ist es theoretisch möglich, einen UEFI-Boot mit einer MBR-Tabelle durchzuführen, jedoch scheint es einige Firmware zu geben, die einen UEFI-MBR-Boot nicht unterstützt. Allerdings ist auch die MBR-Tabelle nicht mehr wirklich Stand der Technik, was man etwa daran erkennen kann, dass nur maximal vier primäre Partitionen möglich sind. Daher wurde UEFI vorwiegend im Hinblick auf die wesentlich modernere GUID-Partitionstabelle (engl. GUID Partition Table, kurz GPT) konzipiert. Es ist also dringlichst anzuraten, für ein UEFI-System eine GPT zu verwenden.

Wer wie ich lieber graphisch partitioniert als mit fdisk, gdisk und parted, kann Gparted verwenden. Da die Arch-Live-ISO freilich keinen graphischen Modus unterstützt, sollte man hier auf eine graphische Distro seiner Wahl umsteigen; ich verwende für solche Zwecke Grml. Da bereits oben der Legacy-Boot aktiviert wurde, sollte jede gängige Linux-Distribution starten.

Eine GPT kann in Gparted angelegt werden, indem unter „Laufwerk → Partitionstabelle erstellen“ die „Erweitert“-Ansicht eingeschaltet wird und dort als Partitionstyp „gpt“ ausgewählt wird:

GPT in Gparted

Anschließend wird einer Besonderheit von UEFI Rechnung getragen: Der MBR wurde durch eine „echte“ Partition ersetzt, sodass umfangreiche Bootkonfigurationen möglich sind, die Bootloader wie GRUB bisher nur durch Trickserei erreichen konnten. Diese sog. EFI System Partition, kurz ESP oder EFISYS, ist eine ordinäre Fat32-Partition mit einem besonderen Partitionstyp. Die empfohlene Größe beträgt 512 MiB und kann problemlos in GParted angelegt werden, ebenso wie alle anderen gewünschten Partitionen. Danach allerdings muss doch noch ein wenig Nacharbeit in gDisk gemacht werden, da GParted den Partitionstyp ESP nicht kennt. gDisk führt ihn als EF00, was wie folgt festgelegt werden kann:

# gdisk /dev/sda
GPT fdisk (gdisk) version 0.8.8

Partition table scan:
  MBR: protective
  BSD: not present
  APM: not present
  GPT: present

Found valid GPT with protective MBR; using GPT.

Command (? for help): p
Disk /dev/sda: 976773168 sectors, 465.8 GiB
Logical sector size: 512 bytes
Disk identifier (GUID): F178DC64-6617-4204-B8F4-92E196D01645
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 976773134
Partitions will be aligned on 8-sector boundaries
Total free space is 23620620 sectors (11.3 GiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1              34         1044224   509.9 MiB   0700  
   2         1044225         9430154   4.0 GiB     8200  
   3         9430155       953152514   450.0 GiB   8300  

Command (? for help): t
Partition number (1-3): 1
Current type is 'EFI System'
Hex code or GUID (L to show codes, Enter = 8300): EF00
Changed type of partition to 'EFI System'

Command (? for help): w

Nun muss noch dem Verzeichnislayout einer EFI-Partition nachgekommen werden:

# mount /dev/sda1 /mnt
# mkdir /mnt/EFI

Damit ist die ESP grundsätzlich fertig eingerichtet. Wer bis hierhin mit Grml oder einer anderen Distribution gearbeitet hat, um die Partitionierung zu erleichtern, rebootet jetzt auf das Arch-Linux-Live-Medium.

Arch-Installation

Nach den üblichen Vorarbeiten (loadkeys de-latin1) muss zunächst wie gewöhnlich die zukünftige Arch-Systempartition eingehangen werden und etwaiger Swap-Speicher aktiviert werden.

# mount /dev/sda3 /mnt
# swapon /dev/sda2

Nun stellt sich allerdings die Frage, wo man die EFI-Systempartition einhängt bzw. ob man das überhaupt tun sollte. Die leichtgewichtigen Bootmanager wie rEFInd, Gummiboot und der eingebaute Bootmanager der Firmware können nur die EFI-Systempartition lesen, sodass, wenn deren Einsatz geplant wäre, in jedem Falle dafür Sorge getragen werden müsste, dass die Linux-Kerneldateien ihren Weg auf die EFI-Systempartition finden. Es gibt daher Advokaten der Methode, die EFI-Systempartition unter /boot/EFI einzuhängen und nach jedem Update die Kerneldatei (vmlinuz-linux) und das initramfs (initramfs-linux.img) nach /boot/EFI/EFI/arch (beachte das doppelte EFI, denn die ESP hat ein eigenes Verzeichnis EFI/!) oder etwas ähnlichem zu kopieren. Andere hängen die EFI-Systempartition direkt als /boot ein und ersparen sich so die Kopierarbeit. Da allerdings die EFISTUB-basierten Bootmanager wie gesagt wegen des Firmware-Bugs auf Lenovo-Laptops nicht oder nur sporadisch funktionieren, könnte man auf eine Einbindung der EFI-Systempartition gänzlich verzichten und sich stattdessen des altbewährten GRUBs bedienen, der EFISTUB nicht verwendet, sondern seinen eigenen Bootloader mitbringt (der schon wesentlich älter ist als EFISTUB und wohl als ausgereift angesehen werden kann), der auch problemlos Kernels von anderen Partitionen laden kann. Ich persönlich möchte mir nicht die Möglichkeit abschneiden, neben GRUB irgendwann auch mal wieder einen leichtgewichtigen Bootmanager/loader zu verwenden, sodass die EFI-Partition irgendwo eingehängt werden sollte. Da ich zu faul bin, herumzukopieren und im Übrigen auch kein Dualboot-Setup pflege, hänge ich die EFI-Partition schlicht als /boot ein.

# mount /dev/sda1 /mnt/boot

Jetzt folgt die eigentliche Arch-Linux-Installation, die jeder so halten sollte, wie er es für richtig hält.

# pacstrap /mnt base
# arch-chroot /mnt

Bootloader

Wer aufmerksam mitgelesen hat, hat möglicherweise schon eine Vorstellung davon, was ich weiters plane. Da die Lenovo-Firmware EFISTUB unmöglich macht, muss ein anderer Bootloader her. Im Wesentlichen stehen da zwei zur Auswahl: GRUB und Syslinux. Da ich bisher immer mit GRUB gearbeitet habe, will ich auch heute dabei bleiben.

Die Installation von GRUB für UEFI unterscheidet sich allerdings ganz wesentlich von der für den klassichen BIOS-Boot. Während GRUB bei letzterem ein Minimalbinary in den Master Boot Record der ersten Festplatte schreibt, das dann weitere Teile von der mit boot markierten Partition unter dem Verzeichnis /grub nachlädt, herrscht bei UEFI aufgrund der eigenen Partition nur für den Bootprozess keine Platzknappheit. Zunächst sind die wesentlichen Pakete im Chroot zu installieren:

# pacman -S dosfstools efibootmgr grub

Das Paket efibootmgr dient zur Bearbeitung der Einträge des Firmware-Bootmanagers, kann an dieser Stelle aber nicht verwendet werden. Wie schon beschrieben, muss ein Legacy-Boot durchgeführt werden, der einen Zugriff auf die EFI-Variablen der Firmware (und damit auf die Bootvariablen) per se unterbindet. Es ist daher nur schonmal für die Zukunft, wenn dereinst das fertige UEFI-gebootete System zur Verfügung steht.

Die Installation von GRUB erfolgt abweichend vom Eintrag im Arch-Wiki wie folgt:

# grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=grub --no-nvram --recheck

Beachte hier insbesondere die Option --no-nvram. Es ist aus dem Legacy-System heraus nicht möglich, die UEFI-Bootparameter zu modifizieren, sodass GRUB es auch gar nicht zu versuchen braucht. Das wird später von Hand erledigt werden müssen.

GRUB muss noch konfiguriert werden. Anders als beim MBR-Boot liegt die GRUB-Binary nun als gewöhnliche Datei /boot/EFI/grub/grubx64.efi vor. Dies ist die Executable, die die UEFI-Firmware starten muss, um GRUB auszuführen (dazu sogleich). Ähnlich wie bei der MBR-Methode sucht sich GRUB seine Module und seine Konfigurationsdatei allerdins aus dem Verzeichnis /grub auf der „Bootpartition“, d.h. bei EFI auf der EFI-System-Partition. Konkret auf meine Installation bezogen, die die EFI-Systempartition als /boot einbindet, dass die GRUB-Konfigurationsdatei unter /boot/grub/grub.cfg vorliegt. Wie üblich kann sie von Hand geschrieben oder generiert werden; ich persönlich ziehe ersteres vor. Dabei gibt es allerdings zwei wesentliche Dinge zu beachten:

  1. Die Partitionsnotation ist anders. Wo es bei MBR-Partitionstabellen etwa (hd0,1) für die erste Partition der ersten Platte heißt, heißt es bei GPTs (hd0,gpt1). GRUB beschwert sich ansonsten, dass es die Festplatte nicht finden kann.
  2. Das Modul efi_gop muss geladen werden. Ansonsten meldet GRUB no suitable video mode found und booting in blind mode, was dazu führt, dass man nur einen schwarzen Bildschirm sieht. Diese Erkenntnis hat mich gestern abend viele Stunden gekostet, bevor ich endlich diese Seite fand, die beiläufig erwähnt, welche Module man im Auge haben sollte.

Mit diesen Erkenntnissen könnte die /boot/grub/grub.cfg so aussehen (beachte den Wert von set root, der auf die EFI-Systempartition zeigt — dort liegt wie beschrieben der Kernel!):

set timeout=5
set default=0

menuentry "Arch Linux" {
  insmod efi_gop
  set root=(hd0,gpt1)
  linux /vmlinuz-linux root=/dev/disk/by-uuid/2c8381e2-bf50-4040-b41f-0cd479afcadf:root ro init=/usr/lib/systemd/systemd
  initrd /initramfs-linux.img
}

menuentry "Arch Linux Fallback" {
  insmod efi_gop
  set root=(hd0,gpt1)
  linux /vmlinuz-linux root=/dev/disk/by-uuid/2c8381e2-bf50-4040-b41f-0cd479afcadf:root ro init=/usr/lib/systemd/systemd
  initrd /initramfs-linux-fallback.img
}

Es kann mit der weiteren Konfiguration des Arch-Systems fortgefahren werden wie gewöhnlich. Da /boot die EFI-Systempartition ist, wird vmlinuz-linux automatisch dort hinterlegt, sodass das GRUB ihn mit der obigen Konfiguration finden kann.

UEFI Firmware

Wenn alle für den ersten Start des Arch-Systems erforderlichen Konfigurationen gemacht wurden, können die Verzeichnisse ausgehangen werden und ein Reboot durchgeführt werden.

# exit # aus dem chroot aussteigen
# umount /mnt/boot
# umount /mnt
# systemctl reboot

Der neue Startvorgang ist wieder mit Return zu unterbrechen, um anschließend mit F1 ins Firmware-Setup zu gelangen. Die zuvor geänderte Einstellung, nur Legacy-Boot durchzuführen wird nun auf „UEFI only“ geändert. Änderungen abspeichern und neustarten. Den Startvorgang wieder mit Return unterbrechen und mit F12 den Arch-Linux-USB-Stick anwählen und im öffnenden Menü sofort die Pfeiltaste unten ↓ drücken. Da es wie oft genug gesagt nicht möglich ist, das Live-Medium mit UEFI zu booten (EFISTUB-Inkompatibilität), wäre es zwecklos, es zu versuchen. Stattdessen die oben schon kurz erwähnte „UEFE Shell v2“ starten. Diese Shell läuft direkt als UEFI-Executable, sodass wir hier die Möglichkeit haben, die Einträge des Firmware-Bootmanagers zu modifizieren.

Zunächst alle erkannten Partitionen anzeigen lassen und auf die EFI-Systempartition wechseln. Das funktioniert ähnlich wie in einer Windows-CMD.

> map
> FS1:
> ls \

UEFI verwendet Backslashes als Pfadtrenner — darauf bei jeder Angabe von Pfaden unbedingt achten, sonst kann es zu unvorhersehbaren Problemen kommen. Eine kurze Übersicht über die UEFI-Shell-Kommandos findet sich im Arch-Wiki. Das für uns interessanteste ist bcfg — damit werden die Einträge des Firmware-Bootmangers bearbeitet. Zunächst alle momentanen Einträge anzeigen:

> bcfg boot dump -b

Bei mir fand sich da noch ein alter Eintrag von Windows, den ich erst einmal getilgt habe:

> bcfg boot rm 7

Von den Einträgen hinsichtlich der Festplatten und USB-Geräte habe ich erstmal die Finger gelassen. Nicht, dass ich am Ende nicht mehr von USB-Sticks booten kann.

Schließlich denn Eintrag für GRUB hinzufügen:

> ls EFI\grub
> bcfg boot add 7 FS1:\EFI\grub\grubx64.efi GRUB

Da die Optionen 1-6 im Normalfalle nicht booten (keine externen USB-Geräte), ist Option 7 die erste relevante. Von nun an sollte UEFI automatisch GRUB laden, der seinerseits wiederum den Linux-Kernel lädt.

UEFI-Shell verlassen:

> halt

(Wenn dieses Kommando hängt, einfach den Rechner ausschalten).