Jak ujarzmić UEFI

Choć może być trudno w to uwierzyć, system, którego używam na co dzień na swojej głównej maszynie, korzeniami sięga mojej pierwszej instalacji Gentoo z 2004 roku. W międzyczasie był przenoszony wielokrotnie między maszynami, ale zasadniczo większość migracji polegała na skopiowaniu plików, naniesieniu niezbędnych modyfikacji w konfiguracji kernela i na deser rekompilacji całości z flagami dla nowego procesora.

Do czego zmierzam? Przez długie lata jako bootloadera używałem lilo, potem gruba i  z przyzwyczajenia trzymałem się tablicy partycji w formacie MBR oraz legacy boot (CSM). Sęk w tym, że świat nie stoi w miejscu i po drodze pojawił się wynalazek o nazwie UEFI. Co więcej, moja aktualna maszyna to na dobrą sprawę ostatnia generacja, która jeszcze obsługuje legacy boot. Widząc to, uznałem, że w ramach future-proofing warto byłoby przejść na tablicę partycji w formacie GPT i UEFI boot, zmniejszając ryzyko, że nie będę mógł odpalić systemu, gdyby przyszło mi przełożyć go do kolejnej maszyny z płytą bez wsparcia dla CSM.

Przy okazji postanowiłem też zastąpić gruba czymś lżejszym, a dokładniej systemd-boot (dawny gummiboot). W moim doświadczeniu grub działa wprawdzie dobrze, ale w pewnym momencie stał się nieco przekomplikowany - ma własne sterowniki dysków, grafiki, systemów plików itd. Tak naprawdę jedyne, czego mi trzeba do szczęścia, to proste menu z listą kerneli i możliwością edycji opcji kernela i to właśnie oferuje systemd-boot. Bardzo prosty i czytelny format configów, który nie wymaga nawet specjalnego generatora (w przeciwieństwie do gruba) też jest zdecydowanym plusem.

Niniejszy wpis nie jest szczegółowym tutorialem, co raczej listą obserwacji, sztuczek i niespodzianek, jakie napotkałem podczas migracji. Dokumentuję je w nadziei, że może oszczędzę komuś niepotrzebnego kombinowania.

Partycjonowanie

Czytając rozmaite howto i strony z dokumentacją, zauważyłem mętne i niespójne informacje co do optymalnego układu partycji, a konkretnie partycji ESP (EFI System Partition). Niektóre poradniki sugerowały osobny /boot i ESP montowane albo w /boot/efi albo w /efi. Ale jak się okazuje, nic nie stoi na przeszkodzie, aby /boot i ESP były w tym samym miejscu, dopóki będzie to partycja FAT32 o odpowiednim rozmiarze. Założyłem więc partycję ESP o rozmiarze 256MB i tam umieściłem swoje kernele i systemd-boot, pamiętając o podaniu odpowiedniej ścieżki przy instalacji: bootctl install --path=/boot

Miałem też jedną czasochłonną niespodziankę przy użyciu gdiska. Po zrobieniu backupa danych po prostu usunąłem starą tablicę partycji MBR i utworzyłem nową tablicę GPT za pomocą opcji "o". Jak się okazuje, z jakiegoś powodu po zapisaniu nowej tablicy partycji devy wskazywały nadal na stare sektory, a nowe partycje nieco się przesunęły, więc przywracane dane zapisywały się w złym miejscu. Najwyraźniej gdisk, w przeciwieństwie do fdiska, nie odświeża automatycznie devów. Zauważyłem problem dopiero, gdy bootctl install wywalił błąd na temat sektora leżącego poza partycją... a po reboocie nie mogłem zamontować świeżo sformatowanych partycji, bo superbloki były w złym miejscu... No cóż, parę kroków musiałem wykonać ponownie, ale za drugim podejściem większych niespodzianek już nie było.

Kernel

Jedną z zalet systemd-boot jest to, że używa bez framebuffera UEFI bez zbędnych ceregieli. Natomiast z framebufferem po boocie nie było już tak różowo i przed odpaleniem się pulpitu straszył mnie zupełnie czarny ekran. To kwestia gustu, ale osobiście lubię widzieć co się dzieje w trakcie startu, by w razie ewentualnych problemów widzieć w czym problem... szczególnie, że przy pierwszym boocie źle wskazałem urządzenie startowe ;) Jakby ktoś był ciekaw, dla partycji root należy używać PARTUUID, a nie UUID ;)

Idąc dalej, jeden z poradników twierdził, że przy nvidia-drivers kernel powinien mieć włączone CONFIG_SYSFB_SIMPLEFB i CONFIG_FB_SIMPLE, kiedy w rzeczywistości właśnie włączenie tych opcji powodowało u mnie dziwne problemy. W rzeczywistości wystarczyło wkompilowane CONFIG_FB_EFI i nvidia-drm.modeset=1 w opcjach kernela. Dodatkowo, aby menu systemd-boot wyświetlał się w natywnej rozdzielczości ekranu, w /boot/loader/loader.conf dodałem linię:

console-mode max

Z kronikarskiego obowiązku, oto lista opcji kernela, które włączyłem przy migracji na UEFI:

CONFIG_EFI=y
CONFIG_EFI_STUB=y
CONFIG_EFI_PARTITION=y
CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK=y
CONFIG_EFI_ESRT=y
CONFIG_EFI_RUNTIME_MAP=y
CONFIG_EFI_DXE_MEM_ATTRIBUTES=y
CONFIG_EFI_RUNTIME_WRAPPERS=y
CONFIG_EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER=y
CONFIG_EFI_CUSTOM_SSDT_OVERLAYS=y
CONFIG_FB_EFI=y
CONFIG_EFIVAR_FS=m

Inne drobiazgi

systemd-boot pozwala na wybranie domyślnego kernela za pomocą bootctl set-default, ale chciałem, żeby pamiętał jaki kernel był ostatnio wybrany z menu. Według mojego researchu jeszcze jakiś czas temu było to niemożliwe, ale szczęśliwie w międzyczasie dodano następującą opcję, którą można dodać w /boot/loader/loader.conf:

default @saved

A na bis postanowiłem jeszcze dodać do swojego bootmenu opcje shutdown i reboot, na wypadek, gdybym chciał szybko wyłączyć/zrestartować omyłkowo włączony system. Jest to możliwe do zrobienia za pomocą funkcji UEFI. Oczywiście nie jestem pierwszą osobą, która wpadła na ten pomysł. Pewien użytkownik Arch Linux napisał kod, który udało mi się skompilować po drobnym kombinowaniu ze ścieżkami do nagłówków (wymaga sys-boot/gnu-efi, ale to powinno być już zainstalowane, jeśli macie systemd-boot). Po skopiowaniu obu binarek do /boot/EFI i utworzeniu dwóch prostych wpisów do loadera działają jak marzenie!

Podsumowanie

A jaki był zysk z popołudnia spędzonego na przerzucaniu danych i dłubaniu w dawno zaniedbanych zakamarkach systemu? Oprócz zabezpieczenia się na przyszłość bez legacy boot jest jeden wymierny zysk z tego całego zamieszania. Po wyłączeniu CSM w biosie mój system startuje zauważalnie szybciej! Nie wiem czy winić tu wczesny bios do Ryzena 3xxx, który obawiam się aktualizować, ale poprzednio komputer spędzał kilkanaście sekund na dumaniu nad swoim żywotem, zanim w ogóle pojawiło się menu gruba. Nigdy nie przeszkadzało mi to na tyle, by zbadać przyczynę, ale teraz żałuję, że nie zrobiłem tego wcześniej :D System startujący w 15 sekund od naciśnięcia powera do w pełni załadowanego pulpitu, bez sztuczek typu hibernacja, hybrid-sleep czy fast boot, to moim zdaniem całkiem zadowalający wynik ;)

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *