Artikel als PDF Gesamtansicht

8 Alternative Bootloaderkonfiguration

Neben dem Erkennen und Laden des Kernelimages ist U-Boot dafür verantwortlich dem Kernel das richtige Device der Rootpartition zu übergeben. Die in Abschnitt 3.2 beschriebene Methode schlägt u.U. fehl, wenn sich Anzahl und/oder Reihenfolge der von U-Boot bzw. Kernel erkannten Speichermedien unterscheiden37. Solche Vermittlungsprobleme lassen sich ausschließen, indem der Kernel veranlasst wird, die Rootpartition anhand eindeutiger Merkmale eigenständig zu erkennen. Diese sind:

Beide Möglichkeiten werden nachfolgend beschrieben. Um die Bootloaderkonfiguration auch von Arch Linux ARM aus durchführen zu können, wird das Paket uboot-tools benötigt. In /etc/fw_env.config ist anschließend die Raute vor dem Eintrag für den DockStar zu entfernen.

#/etc/fw_env.config
# segate dockstar:
/dev/mtd0               0xc0000         0x20000         0x20000

8.1 Initial Ramdisk

Normalerweise wird eine initrd benötigt, um die zum Mounten der Rootpartition benötigten Treiber für Datenträger und Dateisysteme zur Verfügung zu stellen. Diese sind bei Arch Linux ARM jedoch fest in den Kernel integriert, weshalb das Kernelpaket keine initrd bereitstellt. Sie muss folglich nachträglich erstellt werden.

Unter Arch Linux (i686/x86_64) wird anstelle von initrd der Nachfolger initramfs genutzt, das mit mkinitcpio konfiguriert wird. Es werden nur zwei Hooks benötigt:

#/etc/mkinitcpio.conf
HOOKS="base udev"

Das initramfs für den laufenden Kernel (andernfalls Option -k nutzen) wird wie folgt generiert:

[root@alarm ~]# mkinitcpio -v -g /tmp/initramfs-linux.img

Es kann unter Arch Linux ARM nicht direkt genutzt werden, mit mkimage (aus dem Paket uboot-tools) lässt sich daraus aber die eigentliche initial ramdisk erstellen:

[root@alarm ~]# mkimage -A arm -O linux -T ramdisk -C gzip -a 0x00000000 -e 0x00000000 -n initramfs -d /tmp/initramfs-linux.img /boot/uInitrd 

Die Datei /boot/uInitrd wird von U-Boot ohne weitere Konfiguration erkannt und eingebunden. Sodann sorgt udev für das Anlegen eines dem Label der Rootpartition (hier: root) entsprechenden Links unter /dev/disk/by-label/, der als Kernelparameter genutzt werden kann. Außerdem setze ich rootwait anstelle von rootdelay ein:

[root@alarm ~]# fw_setenv usb_set_bootargs 'setenv bootargs console=$console root=/dev/disk/by-label/root rootwait rootfstype=ext4 $mtdparts $usb_custom_params'

Alternativ kann auch wie in einem Blog beschrieben usb_init angepasst werden. Anstelle des Labels sollte sich auch die UUID über den Link unter /dev/disk/by-uuid/ nutzen lassen, ich habe dies jedoch nicht ausprobiert. Problematisch ist dagegen die Verwendung der Schreibweisen root=LABEL=... und root=UUID=.... Beide haben nicht zuverlässig funktioniert, näheres im Forum.

8.2 GPT mit hybridem MBR

Speichermedien mit GPT können vom Linux Kernel ab Version 2.6.37 genutzt werden. Die notwendige Option CONFIG_EFI_PARTITION=y ist im ARCH-Kernel aktiviert und sollte natürlich ggf. auch bei einem Custom-Kernel ausgewählt sein.

Zum Anlegen einer GPT dient das Programm gdisk. Wurde der Stick bereits mit fdisk formatiert, kann gdisk die GPT unter Verwendung der im MBR vorhandenen Partitionstabelle auch nachträglich anlegen. Die notwendigen Schritte habe ich an meinem Linux-PC durchgeführt. Wie schon in Abschnitt 2.1 verwende ich wieder sdx stellvertretend als Device des USB-Sticks (von dem ich zuvor sicherheitshalber ein Backup angelegt habe).

[root@linux ~]# gdisk /dev/sdx

Warnhinweise sollte man beachten und das Programm ggf. mit 'q' abbrechen. Insgesamt gab es zwei Hürden zu nehmen, die ich hier genauer beschreibe:

8.2.1 Verkleinern der letzten Partition

Aus Redundanzgründen beansprucht die GPT auch einen Bereich am Ende des Speichermediums, der jedoch bereits Bestandteil der dritten Partition ist. Folglich vermeldet gdisk zunächst:

Warning! Secondary partition table overlaps the last partition by
33 blocks!
You will need to delete this partition or resize it in another utility.

Es war also erforderlich zunächst die letzte (dritte) Partition um 33 Blöcke (gemeint sind Sektoren á 512 Byte) zu verkürzen. Dazu muss zunächst das auf der Partition befindliche Dateisystem mit resize2fs verkleinert werden. Dabei ist die Blockgröße des Dateisystems zu berücksichtigen:

[root@linux ~]# dumpe2fs /dev/sdx3|grep "^Block"
dumpe2fs 1.41.14 (22-Dec-2010)
Block count:              3590912
Block size:               4096
Blocks per group:         32768

Die Anzahl der Dateisystemblöcke muss folglich um 33*512/4096, also mindestens 5 reduziert werden. Es schadet aber nichts, das Dateisystem zunächst stärker als nötig zu verkleinern (s.u.). In jedem Fall muss es vorher mit e2fsck einer Prüfung unterzogen werden.

[root@linux ~]# e2fsck -f /dev/sdx3
[root@linux ~]# resize2fs /dev/sdx3 3590907
[root@linux ~]# fdisk /dev/sdx

Das Verkleinern der Partition erfolgt mit fdisk einfach durch Löschen und erneutes Anlegen (d-3-n-p-3). Der vorgeschlagene Startsektor kann übernommen werden, der letzte Sektor ist jedoch um 33 auf 31252446 zu verringern, vgl. Abschnitt 2.1.

Optional lässt sich das Dateisystem mit resize2fs dann wieder automatisch auf die durch die neue Partitionsgröße vorgegebene maximale Größe erweitern. Bei der beschriebenen Vorgehensweise erübrigt sich dies:

[root@linux ~]# resize2fs /dev/sdx3
resize2fs 1.41.14 (22-Dec-2010)
Das Dateisystem ist schon 3590907 Blöcke groß. Nichts zu tun!

Zuletzt genügt ein erneuter Aufruf von gdisk /dev/sdx zur Umwandlung des MBR in eine GPT. Sollten keine Warnungen erscheinen, beendet man dazu einfach mit 'w'.

8.2.2 Erstellung eines hybriden MBRs

Der Versuch den so manipulierten Stick nun testweise wieder am DockStar zu booten schlug fehl. Vermittels netcat stellte sich heraus, dass U-Boot die Partitionen das Sticks nicht mehr zu lesen vermochte:

Loading file "/boot/uImage" from usb device 1:1 (usbdb1)
Failed to mount ext2 filesystem...
** Bad ext2 partition or disk - usb 1:1 **

Abhilfe sollte laut eines Forumsbeitrags das Erstellen eines hybriden MBR bringen38, der nur die Bootpartition als erste Partition enhält. Hier die genaue Vorgehensweise mit gdisk unter Zuhilfenahmen der GPT Dokumentation.

Command (? for help): r

Recovery/transformation command (? for help): h

WARNING! Hybrid MBRs are flaky and dangerous! If you decide not to use one,
just hit the Enter key at the below prompt and your MBR partition table will
be untouched.

Type from one to three GPT partition numbers, separated by spaces, to be
added to the hybrid MBR, in sequence: 1
Place EFI GPT (0xEE) partition first in MBR (good for GRUB)? (Y/N): n

Creating entry for GPT partition #1 (MBR partition #1)
Enter an MBR hex code (default 83): 
Set the bootable flag? (Y/N): y

Unused partition space(s) found. Use one to protect more partitions? (Y/N): n

Recovery/transformation command (? for help): w

Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!

Do you want to proceed? (Y/N): y
OK; writing new GUID partition table (GPT).
The operation has completed successfully.

Erfreulicherweise erkannte U-Boot den Stick nun wie bisher. Um den Vorteil der GPT zu nutzen brauchen wir noch die “Partition unique GUID” der Rootpartition. Diese bringt - unter Arch Linux ARM - ein erneuter Aufruf von gdisk nach Eingabe von 'i' und Partitionsnummer zu Vorschein:

Command (? for help): i           
Partition number (1-3): 2
Partition GUID code: 8EC76FBA-2272-45AF-A844-94ED164A1B86 (Unknown)
Partition unique GUID: 43152BE8-EA6D-47EE-A014-59C52C383DE0
First sector: 67584 (at 33.0 MiB)
Last sector: 2525183 (at 1.2 GiB)
Partition size: 2457600 sectors (1.2 GiB)
Attribute flags: 0000000000000000
Partition name: Linux filesystem

Mit dieser Information kann die Bootvariable wie folgt angepasst werden:

[root@alarm ~]# fw_setenv usb_set_bootargs 'setenv bootargs console=$console root=PARTUUID=43152BE8-EA6D-47EE-A014-59C52C383DE0 rootwait rootfstype=ext4 $mtdparts $usb_custom_params'

Vor dem Reboot sollte man eine etwaig vorhandene /boot/uInitrd wieder löschen oder umbenennen. Andernfalls wird der Bootvorgang nach Laden des Kernels nicht fortgesetzt.

Die PARTUUID kann mit gdisk auch auf einen bestimmten Wert eingestellt werden (x-c-2). So lässt sich etwa ein Backup-USB-Stick mit identischer PARTUUID herstellen, von dem ohne erneute Anpassung des Bootmanagers ersatzweise gebootet werden kann.

Kontakt Alternative Bootloaderkonfiguration

  1. Nachdem ich jüngst eine der speziell für den Betrieb am oberen USB-Anschluss der DockStar vorgesehenen 2,5" Festplatten “FreeAgent Go” erworben hatte, musste ich mittels Netzkonsole festellen, dass diese von U-Boot nicht zuverlässig erkannt wurde: War beispielsweise neben der Festplatte nur der USB-Stick angeschlossen, wurde dieser von U-Boot als erstes/einziges Device erkannt und gemäß Abschnitt 3.2 folglich sda2 als Rootpartition übermittelt. Aus Kernelsicht stellte sda jedoch die Festplatte dar, so dass der Bootvorgang nicht fortgesetzt werden konnte.

  2. Mit Mainline U-Boot erübrigt sich die Erstellung eines hybriden MBR.