[root tip] [How To] Convert from GRUB to UKI

Convert system from GRUB to UKI

The UKI is a Unified Kernel Image - a couple of benefits

  • faster startup
  • for encrypted systems better algorithms and faster decryption
  • simplified maintenance
  • signing (for use with Secure Boot)
  • using the latest LTS greatly simplifies ongoing kernel maintenance

I have considered if there are any cons - I couldn’t think of any - but after carefully considering what could possibly go wrong

  • watch out and verify that your UKI build successfully
  • do not change your kernel cmdline arguments without proper validation
  • do not blindly restart your system

Assumptions

A default Manjaro Linux encrypted standalone UEFI installation (no dual/multi booting)

  1. system disk is /dev/nvme0n1 ESP is first partiion (1) and system is on second partition (2)
  2. default luks container encrypted with luks1 (default Calamares)
  3. default root file system is btrfs
  4. kernel is 6.18

EFI partition

A common Manjaro Linux EFI partition size (created by Calamares) is 300MB.
A unified kernel (without Nvidia) is around 55MB so there should be room on the EFI partition.

In any case check the size (example is my workstation configured with UKI)

 $ sudo du -h /efi
55M     /efi/EFI/Linux
4,0K    /efi/EFI/manjaro/fw
80K     /efi/EFI/manjaro
55M     /efi/EFI
12K     /efi/loader/credentials
20K     /efi/loader
56M     /efi

Avoiding errors

To avoid errors with disk and partition I will use variables for the partitions.

Enter the following (you may adjust this if your device is not nvme0n1)

disk="/dev/nvme0n1"
efipart="/dev/nvme0n1p1"
rootpart="/dev/nvme0n1p2"

Boot a live ISO

Open a terminal and switch to root context using su

convert to luks2

Convert the container on the root partition to luks2 - the benefit is better encryption algorithms and faster unlocking

cryptsetup convert $rootpart --type luks2
cryptsetup luksConvertKey $rootpart --pbkdf argon2id

using labels

Using labels simplifies maintenance, so add the label cryptsystem to the root partition

e2label cryptsystem $rootpart

Unlock the root container

cryptsetup open $rootpart system

Mount the root btrfs filesystem

Assuming a default Manjaro btrfs file system layout

mount -t btrfs -o subvol=@      /dev/mapper/system /mnt
mount -t btrfs -o subvol=@home  /dev/mapper/system /mnt/home
mount -t btrfs -o subvol=@cache /dev/mapper/system /mnt/var/cache
mount -t btrfs -o subvol=@log   /dev/mapper/system /mnt/var/log

label the btrfs filesystem

Simplify the maintenance by adding the label system to your btrfs file root

btrfs filesystem label /mnt system
udevadm trigger

label ext4 or xfs and mount

Note: Since btrfs is the default on new Manjaro Linux installations, this guide has been written with btrfs in mind, but the approach is equally valid if your root file system is ext4 or xfs. Simply adjust the mount procedure and the labelling of the root file system.

To label your file system inside the container

  • ext4: e2label system /dev/mapper/system
  • xfs: xfs_admin -L system /dev/mapper/system
mount /dev/mapper/system /mnt

Label and mount the efi partition

Label the efi partition with EFI

fatlabel $efipart EFI

Using the UEFI standard, create the /efi mountpoint inside the root mountpoint, we also need the Linux subfolder in the EFI folder.

Ensure there is no folder or symlinking named efi in the mounted root file system, them create the folder, mount the partition and finally create the location for the UKI

rm -rf /mnt/efi
mkdir /mnt/efi
mount $efipart /mnt/efi
mkdir /mnt/efi/EFI/Linux

Mount system devices

mount --bind /dev /mnt/dev
mount --bind /proc /mnt/proc
mount --bind /sys /mnt/sys
mount --bind /run /mnt/run

Enter chroot

manjaro-chroot /mnt /bin/bash

Configuration

edit: the file /etc/mkinitcpio.d/linux618.preset. The file has a lot of content - mostly commented - so I will only list the important bits here. Ensure the rest is commented

ALL_kver="/boot/vmlinuz-6.18-x86_64"
PRESETS=('default')
default_uki="/efi/EFI/Linux/manjaro-6.18.efi"
default_options="--splash /usr/share/systemd/bootctl/splash-manjaro.bmp"

edit: add a FONT and FONT_MAP to /etc/vconsole.conf this will make it possible to use non-us characters in the passphrase ref: Linux console - ArchWiki

FONT=lat2-16
FONT_MAP=8859-1

edit: remove or comment root directive from /etc/crypttab (no use for it)
edit: change /etc/fstab to use /efi as mountpoint for ESP (EFI System Partition) (instead of /boot/efi)
edit: simplify maintenance by modifying /etc/fstab to use a partition label instead of uuid

The following is samples from my working systems (laptop and workstation)

LABEL=EFI     /efi        vfat   rw,relatime,umask=0077,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro  0  2

btrfs

LABEL=system  /           btrfs  subvol=/@,defaults,compress=zstd:1       0  0
LABEL=system  /home       btrfs  subvol=/@home,defaults,compress=zstd:1   0  0
LABEL=system  /var/log    btrfs  subvol=/@log,defaults,compress=zstd:1    0  0
LABEL=system  /var/cache  btrfs  subvol=/@cache,defaults,compress=zstd:1  0  0

ext4

LABEL=system  /  ext4  rw,noatime  0  1 

xfs

LABEL=system  /  xfs  rw,relatime,inode64,logbufs=8,logbsize=32k,noquota  0  0 

create: file /etc/crypttab.initramfs with content, this is where we point the root file system (instead of the crypttab file above)

system /dev/disk/by-partlabel/cryptsystem none timeout=120

create: file /etc/kernel/cmdline with content.
Using btrfs

fbcon=nodefer rd.luks.allow-discards bgrt_disable root=LABEL=system rootflags=subvol=@,rw quiet splash udevlog_priority=3 vt.global_cursor_default=0

Using ext4 or xfs

fbcon=nodefer rd.luks.allow-discards bgrt_disable root=LABEL=system quiet splash udevlog_priority=3 vt.global_cursor_default=0

edit: file /etc/mkinitcpio.conf (the dots are representing existing content)

...
FILES=()
...
HOOKS=(systemd microcode autodetect kms modconf block keyboard sd-vconsole sd-encrypt filesystems plymouth fsck)
...

configure: plymouth to use a theme like bgrt or spinfinity

plymouth-set-default-theme bgrt

generate: the unified kernel (assuming linux 6.18 kernel)

mkinitcpio -p linux618

configure: UEFI firmware to load the UKI

efibootmgr --create --disk $disk --part 1 --loader "/EFI/Linux/manjaro-6.18.efi" --label "Manjaro Linux 6.18LTS" --unicode

housekeeping: Remove grub and related files

pacman -Rns grub-theme-manjaro install-grub update-grub grub grub-btrfs mkinitcpio-openswap

Be sure to do some house keeping - remove obsolete kernels and their configuration.

Recovery

When you have created your first UKI and succesfully booted your system, copy the UKI to a recovery image.

sudo cp /efi/EFI/Linux/manjaro-6.18.efi /efi/EFI/Linux/recovery.efi

Then add the image to your firmware

sudo efibootmgr --create --disk $disk --part 1 --loader "/EFI/Linux/recovery.efi" --label "Recovery 6.18LTS" --unicode

Should it need be - you can use your system’s firmware boot override to select the Recovery image to get to a working system where you can fix the issue.

Another option is to use rEFInd - a graphical utility for listing available EFI binaries.

5 Likes