ユニファイドカーネルイメージ
ユニファイドカーネルイメージ (UKI) は、単一の実行可能ファイルであり、UEFI ファームウェアから直接起動するか、ほとんどまたは全く設定を必要とせずにブートローダーによって自動的に取得されます。これは systemd-stub(7) のような UEFI ブートスタブプログラム、Linux カーネルイメージ、initrd、および その他のリソース を単一の UEFI PE ファイルに組み合わせたものです。
このファイルは、したがってこれらのすべての要素を署名して Secure Boot で使用することが容易になります。
目次
ユニファイドカーネルイメージの準備
UKI (Unified Kernel Image) イメージを生成し、適切な場所 ("esp/Linux" ディレクトリ) にインストールする方法はいくつかあります。現在、この機能を実行するためのツールがいくつか競合しているので、ニーズと好みに応じて以下のいずれかを選択してください。
mkinitcpio
mkinitcpio は、systemd-ukify がインストールされていない限り、UKI (Unified Kernel Image) を自身で組み立てます。systemd-ukify がインストールされている場合は、--no-ukify
オプションで明示的に無効にしない限り、UKI の作成は "ukify" にオフロードされます。
カーネルコマンドライン
mkinitcpio は、/etc/cmdline.d
ディレクトリ内のコマンドライン ファイルからのカーネルパラメータの読み取りをサポートします。Mkinitcpio は、このディレクトリ内の .conf
拡張子を持つすべてのファイルの内容を連結し、それらを使用してカーネルコマンドラインを生成します。コマンドラインファイル内の # 文字で始まる行はコメントとして扱われ、mkinitcpio によって無視されます。マイクロコードと initramfs を指す エントリを削除 するように注意してください。
例:
/etc/cmdline.d/root.conf
root=UUID=0a3407de-014b-458b-b5c1-848e92a327a3 rw
/etc/cmdline.d/security.conf
# enable apparmor lsm=landlock,lockdown,yama,integrity,apparmor,bpf audit=1 audit_backlog_limit=256
あるいは、/etc/kernel/cmdline
を使用してカーネルコマンドラインを設定することもできます。
例:
/etc/kernel/cmdline
root=UUID=0a3407de-014b-458b-b5c1-848e92a327a3 rw quiet bgrt_disable
.preset ファイル
次に、/etc/mkinitcpio.d/linux.preset
、または使用しているプリセットを、EFI システムパーティション の適切なマウントポイントを指定して、以下のように変更します:
PRESETS=
の各項目について、PRESET_uki=
パラメータのコメントを解除する (つまり#
を削除する)、- 冗長な
initramfs-*.img
ファイルを保存しないように、PRESET_image=
をコメントアウトする、 - オプションとして、スプラッシュイメージを追加したい各
PRESET_options=
行に--splash
パラメータを追加またはコメント解除します。
以下は linux カーネルと Arch スプラッシュスクリーンの linux.preset
の例です。
/etc/mkinitcpio.d/linux.preset
# mkinitcpio preset file for the 'linux' package #ALL_config="/etc/mkinitcpio.conf" ALL_kver="/boot/vmlinuz-linux" PRESETS=('default' 'fallback') #default_config="/etc/mkinitcpio.conf" #default_image="/boot/initramfs-linux.img" default_uki="esp/EFI/Linux/arch-linux.efi" default_options="--splash=/usr/share/systemd/bootctl/splash-arch.bmp" #fallback_config="/etc/mkinitcpio.conf" #fallback_image="/boot/initramfs-linux-fallback.img" fallback_uki="esp/EFI/Linux/arch-linux-fallback.efi" fallback_options="-S autodetect"
pacman フック
systemd-stub (systemd の一部)、microcode (intel-ucode と amd-ucode の両方)、および linux カーネルの更新は、自動的に UKI (Unified Kernel Image) の再構築をトリガーします。ただし、/etc/pacman.d/hooks/
ディレクトリにある他の pacman フック (例えば、NVIDIA ドライバー のものなど) を確認することをお勧めします。
UKI の構築
最後に、UKI のディレクトリが存在することを確認し、initramfs を再生成 します。たとえば、linux プリセットの場合は次のようになります。
# mkdir -p esp/EFI/Linux # mkinitcpio -p linux
必要に応じて、残っている initramfs-*.img
を /boot
または /efi
から削除します。
kernel-install
確実に kernel-install が 正しく設定されている ことを確認してください。
UKI を生成するには、systemd-ukify をインストールし、kernel-install
の layout を uki
に設定します。
/etc/kernel/install.conf
layout=uki
#ukify の設定は、kernel-install で使用するために、/etc/kernel/uki.conf
で行う必要があります。例:
/etc/kernel/uki.conf
[UKI] Splash=/usr/share/systemd/bootctl/splash-arch.bmp
あるいは、mkinitcpio が UKI を生成するように、それをデフォルトの uki_generator
として設定します。
/etc/kernel/install.conf
layout=uki uki_generator=mkinitcpio
この場合、systemd-ukify は不要です。別の initrd_generator
を設定することもできます。kernel-install(8) を参照してください。
変更を有効にするには、使用しているカーネルパッケージを再インストールしてください。
dracut
こちらを参照して下さい dracut#ユニファイドカーネルイメージ と dracut#カーネルのアップグレード時に新しい initramfs を生成
ukify
systemd-ukify パッケージを インストール します。ukify は単独で initramfs を生成できないため、必要な場合は、dracut、mkinitcpio、または booster を使用して生成する必要があります。
最小限の動作例は次のようになります。
# ukify build --linux=/boot/vmlinuz-linux \ --initrd=/boot/initramfs-linux.img \ --cmdline="quiet rw"
詳細については、ukify(1)を参照してください。
intel ucode および /efi マウント ESP を使用した通常のカーネルイメージの systemd サービスを使用した自動 UKI 構築の例:
手動で
使用するカーネルコマンドラインをファイルに記述し、objcopy(1) を使用してバンドルファイルを作成します。
マイクロコード の場合は、まず次のようにマイクロコードファイルと initrd を連結します。
$ cat esp/cpu_manufacturer-ucode.img esp/initramfs-linux.img > /tmp/combined_initrd.img
統合カーネルイメージを構築するときは、/tmp/combined_initrd.img
を initrd として渡します。このファイルは後で削除できます。
$ align="$(objdump -p /usr/lib/systemd/boot/efi/linuxx64.efi.stub | awk '{ if ($1 == "SectionAlignment"){print $2} }')" $ align=$((16#$align)) $ osrel_offs="$(objdump -h "/usr/lib/systemd/boot/efi/linuxx64.efi.stub" | awk 'NF==7 {size=strtonum("0x"$3); offset=strtonum("0x"$4)} END {print size + offset}')" $ osrel_offs=$((osrel_offs + "$align" - osrel_offs % "$align")) $ cmdline_offs=$((osrel_offs + $(stat -Lc%s "/usr/lib/os-release"))) $ cmdline_offs=$((cmdline_offs + "$align" - cmdline_offs % "$align")) $ splash_offs=$((cmdline_offs + $(stat -Lc%s "/etc/kernel/cmdline"))) $ splash_offs=$((splash_offs + "$align" - splash_offs % "$align")) $ initrd_offs=$((splash_offs + $(stat -Lc%s "/usr/share/systemd/bootctl/splash-arch.bmp"))) $ initrd_offs=$((initrd_offs + "$align" - initrd_offs % "$align")) $ linux_offs=$((initrd_offs + $(stat -Lc%s "initrd-file"))) $ linux_offs=$((linux_offs + "$align" - linux_offs % "$align")) $ objcopy \ --add-section .osrel="/usr/lib/os-release" --change-section-vma .osrel=$(printf 0x%x $osrel_offs) \ --add-section .cmdline="/etc/kernel/cmdline" \ --change-section-vma .cmdline=$(printf 0x%x $cmdline_offs) \ --add-section .splash="/usr/share/systemd/bootctl/splash-arch.bmp" \ --change-section-vma .splash=$(printf 0x%x $splash_offs) \ --add-section .initrd="initrd-file" \ --change-section-vma .initrd=$(printf 0x%x $initrd_offs) \ --add-section .linux="vmlinuz-file" \ --change-section-vma .linux=$(printf 0x%x $linux_offs) \ "/usr/lib/systemd/boot/efi/linuxx64.efi.stub" "linux.efi"
注意すべき点がいくつかあります:
- [1] で推奨されているように、オフセットは動的に計算されるので、セクションが重なることはありません。
- セクションは、PE スタブの
SectionAlignment
フィールドが示す値 (通常は 0x1000) にアラインメントされます。 - カーネルイメージは、[2] で述べられているように、インプレース解凍で後続のセクションが上書きされるのを防ぐために、最後のセクションにある必要があります。
イメージを作成したら、それを EFI システムパーティションにコピーします。
# cp linux.efi esp/EFI/Linux/
セキュアブート 用の UKI への署名
sbctl
sbctl は、更新されたバイナリに署名するための kernel-install スクリプト、mkinitcpio ポストフック、および pacman フックを提供します。
mkinitcpio
mkinitcpio ポストフック を使用することで、生成された Unified Kernel Image に セキュアブート 用の署名を付けることができます。以下のファイルを作成し、実行可能にしてください。
/etc/initcpio/post/uki-sbsign
#!/usr/bin/env bash uki="$3" [[ -n "uki"]]∣∣exit0keypairs=(′′/path/to/′′db.key′′/path/to/′′db.crt)for((i=0;i<{#keypairs[@]}; i+=2 )); do key="${keypairs[$i]}" cert="${keypairs[(( i + 1 ))]}" if ! sbverify --cert "$cert" "$uki" &>/dev/null; then sbsign --key "$key" --cert "$cert" --output "$uki" "$uki" fi done
/path/to/db.key
と /path/to/db.crt
を、イメージの署名に使用するキーペアのパスに置き換えてください。
ukify
sbsigntools をインストールし、/etc/kernel/uki.conf
で --secureboot-private-key
と --secureboot-certificate
を指定します。
起動方法
Limine
Limine は Unified Kernel Image (UKI) を自動的に検出しません。ただし、limine.conf
を手動で構成して UKI をロードできます。
例 1: デフォルトの EFI システムパーティションから UKI を起動する
UKI ファイルが esp/EFI/Linux/
に保存されている場合は、次の設定を limine.conf
に追加します。
limine.conf
/Arch Linux protocol: efi_chainload image_path: boot():/EFI/Linux/arch-linux.efi
例 2: 別の EFI パーティションから UKI を起動する
UKI ファイルが別のディスク上の別の EFI パーティションにある場合は、uuid(partition UUID)
を使用します。
limine.conf
/Arch Linux protocol: efi_chainload image_path: uuid(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx):/EFI/Linux/arch-linux.efi
サポートされているパスと設定オプションの詳細については、Limine Paths ドキュメント を参照してください。
systemd-boot
systemd-boot は esp/EFI/Linux/
内でユニファイドカーネルイメージを検索しますので、それ以上の設定は必要ありません。sd-boot(7) § FILES を見て下さい。
rEFInd
rEFInd は、EFI システム パーティション上のユニファイドカーネルイメージを自動検出し、それらをロードできます。refind.conf
で手動で指定することもできます。デフォルトでは次の場所にあります。
esp/EFI/refind/refind.conf
menuentry Linux { loader esp/EFI/Linux/archlinux-linux.efi }
イメージが ESP のルートにある場合、rEFInd は次のようにその名前のみを必要とします: loader archlinux-linux.efi
この方法で起動すると、esp/EFI/refind_linux.conf
からのカーネルパラメータは渡されません。
GRUB
rEFInd と同様に、GRUB は GRUB#ユニファイドカーネルイメージをチェインロード で説明されているように EFI UKI をチェーンロードできます。
UEFI から直接起動
efibootmgr を使って .efi ファイルに UEFI ブートエントリを作成することができます。
# efibootmgr --create --disk /dev/sdX --part partition_number --label "Arch Linux" --loader '\EFI\Linux\arch-linux.efi' --unicode
オプションの説明は efibootmgr(8) をご覧ください。