EFI スタブ
- CONFIG_PM_STD_PARTITION for hibernation
多くのコンピュータに存在する (U)EFI ファームウェアはブートマネージャとして機能し、対応した EFI ブートローダを使用してシステムをブートすることができます。カーネル 自体をこのようなブートローダ (EFI スタブと呼ばれます) にすることで、2 次ブートローダを必要とせずにブートすることができます。この記事では、カーネルを設定して、EFI モードで実行中のコンピュータの EFI システムパーティション (ESP) にインストールするための手順を提供します。
UEFI の実装はベンダーによって異なっており、すべての UEFI システムで EFI スタブによるブートの動作が保証されているわけではありません。EFI スタブによる(自動)ブートを試す前に、バックアップのブート方法を必ず確保してください。
カーネル設定
EFI スタブサポート
以下のカーネル設定オプションが有効化されていなくてはなりません:
Processor type and features --->
[*] EFI runtime service support
[*] EFI stub support
[ ] EFI mixed-mode support (OPTIONAL)
EFI mixed-mode support は、CPU が 64 ビットモードに対応しており、EFI handover が有効化されている場合に、32 ビットファームウェアから 64 ビットカーネルをブートするためにのみ必要です。
インストール
自動
EFI スタブによる自動ブートは、efistub USE フラグが有効化されている場合、sys-kernel/installkernel によって提供されます。これにより、通常のブートレイアウトが /boot から EFI System Partition 上の EFI/Gentoo へと変更され、インストール・削除されたカーネルのブートエントリを追加・削除するために app-emulation/virt-firmware の kernel-bootcfg が実行されます。Installkernel は、カーネルの make install または Distribution Kernel の post-install フェーズによって自動的に実行されます。したがって、新しいカーネルをインストールした際に特別な操作は不要ですが、新しいカーネルでのブートに成功した時に永続的な項目を自動的に作成するには、app-emulation/virt-firmware の kernel-bootcfg-boot-successful init サービスを有効にしてください。
systemd システムでは:
root #
systemctl --enable --now kernel-bootcfg-boot-successful.service
OpenRC システムでは:
root #
rc-update add kernel-bootcfg-boot-successful default
登録されるカーネルイメージが Unified Kernel Image ではない場合、新しい項目のカーネルコマンドラインは以下の順番で読み込まれます:
- /etc/kernel/cmdline
- /usr/lib/kernel/cmdline
- /proc/cmdline
さらに、カーネルのインストール中に initramfs が生成された場合、カーネルコマンドライン引数 initrd= が自動的に追加されます。一方、登録されるカーネルが Unified Kernel Image の場合、新しいエントリにはコマンドラインは追加されません。代わりに Unified Kernel Image に組み込まれているコマンドラインが使用されますが、この組み込みコマンドラインの内容も通常は UKI が生成される際に同じファイルから読み込まれます。
sys-kernel/installkernel の efistub USE フラグは systemd USE フラグを必要とします。しかし、この systemd フラグは systemd init システムへの依存関係を強制しません。この systemd フラグによる依存関係は、sys-apps/systemd-utils の boot 及び kernel-install フラグがあれば満たされるため、これは OpenRC システムでも動作します。
手動
EFI スタブサポートを付けてカーネルを設定したら (ESP が /efi にマウントされていると仮定して)。システムによっては /efi/efi が既に存在することがあり、その場合はそれを使用しなくてはなりません。/efi/EFI (または /efi/efi が既に存在する場合はそちら) の下に個別のディレクトリを作成することが推奨されます。以下では example の名前を使用します:
root #
mkdir -p /efi/EFI/example
カーネルは現在のカーネルディレクトリから作成され、新しいディレクトリにコピーされます。これはカーネルを /efi/EFI/example/bzImage.efi にインストールします:
/usr/src/linux #
make && make modules_install && cp arch/x86/boot/bzImage /efi/EFI/example/bzImage.efi
カーネルをアップグレードするときには、動作することが分かっている古いバージョンを残しておくことが推奨されます:
user $
tree -L 3 /efi
/efi └── EFI └── example ├── bzImage-6.1.67.efi └── bzImage-6.1.70.efi
ルートパーティション設定
UEFI から直接ブートするためには、ブートするシステムのルート (/) パーティションがどこにあるのかをカーネルまたは initramfs が認識していなくてはなりません。grub などのブートマネージャを使用する場合は、カーネルはルートパーティションをどこから探せばよいかの情報を、ブートマネージャからコマンドライン引数を介して取得します。スタブカーネルを使用する場合は、カーネルにこの情報を渡すために使用できる方法として 2 つの選択肢があります - これらの選択肢から一方を選択してください:
選択肢 1: カーネル内で設定する =
Processor type and features --->
[*] Built-in kernel command line
(root=PARTUUID=adf55784-15d9-4ca3-bb3f-56de0b35d88d ro)
値 adf55784-15d9-4ca3-bb3f-56de0b35d88d は例であり、実際のルートパーティションの値で置き換えなくてはなりません。これは blkid コマンドを使用して得ることができます:
root #
blkid | grep sda3
/dev/sda3: UUID="d1e0c1e0-3a40-42c5-8931-cfa2c7deae32" TYPE="ext4" PARTUUID="adf55784-15d9-4ca3-bb3f-56de0b35d88d"
選択肢 2: UEFI 内で設定する
カーネルコマンドライン引数付きのエントリを追加するには:
root #
efibootmgr --create --disk /dev/sda --label "Gentoo EFI Stub" --loader "\EFI\example\bzImage.efi" -u "root=/dev/sda3"
ルートの場所は PARTUUID を使用して、または initramfs を使用する場合には (ファイルシステムの) UUID を使用して設定するほうが、一般的により好ましく間違いを起こしにくいです。
EFI ファームウェア設定
カーネルファイルが /efi/EFI/example/bzImage.efi にある場合は、ブートエントリは以下で追加することができます:
root #
efibootmgr --create --disk /dev/sda --label "Gentoo EFI Stub" --loader "\EFI\example\bzImage.efi"
さらなる例を efibootmgr で見つけることができます。
追加可能: initramfs とともに併用する
外部の (CPIO アーカイブの) initramfs とともにカーネルを使用する場合、追加の手順が必要です。dist-kernel をビルドする場合または genkernel を使用する場合は、必ず initramfs が作成されます。dist-kernel を使用する場合、この initramfs は "initrd" という名前が付けられ、/usr/src/linux-6.1.57-gentoo-dist/arch/x86/boot/initrd に置かれます。このファイルを ESP にコピーする必要があります:
root #
cp /path/to/my/initramfs/myinitrd.cpio.gz /efi/EFI/example/initrd.cpio.gz
カーネルは initramfs をどこから探すべきかの情報を必要とし、initramfs はルートパーティションをどこから探すべきかの情報を必要とします。UEFI は両方の情報を与えなくてはなりません:
root #
efibootmgr -c -d /dev/sda -p 1 -L "Gentoo EFI Stub" -l '\EFI\example\bzImage.efi' -u 'root=UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx initrd=\EFI\example\initrd.cpio.gz'
フォーラム投稿はそれについてより詳しく説明しています - さらにユーザのエラーをいくつか修正しています:
Forums topic - Booting UEFI without Grub
Early Userspace Mounting を使用する場合は、Generating the Initramfs および Using a Stub Kernel の節でそれについて詳しく説明しています。
省略可能: 埋め込み initramfs
また、initramfs をカーネルに直接組み込むこともできます。利点としては、Secure Boot がカーネルを検証する際に initfamfs も検証されること、ブートプロセスや EFI パーティションが単純になること、(呼出元で initfamfs を指定する必要がないため)簡単に手動でカーネルを読み込めることなどがあります。欠点は、柔軟性が低くなること、ミスが起こりやすいこと、一般的でないブート構成を使用することなどです。
initramfs に Microcode が含まれている場合、更新を受け取ることがセキュリティ上重要です。initramfs は、カーネルに組み込まれている場合は独立して更新することができないため、initramfs が更新されるたびにカーネルをビルドしなおす必要があります。具体的には、以下のことに注意する必要があります:
- カーネルを再ビルドする前に を実行しない場合、最後のビルドから残っているキャッシュされた initramfs CPIO アーカイブを削除するために
root #
make clean
を実行してください。root #
rm usr/initramfs_data.cpio
- initramfs に更新がある場合、カーネルを再ビルド・再インストールしてください。
- initramfs が sys-apps/portage によって管理されている場合、initramfs をカーネルより前に更新するようにしてください。
カーネルは、(例えば Dracut で生成されるような) CPIO ファイルと、CPIO アーカイブに圧縮されるソースディレクトリの両方をサポートしています。以下では後者を /usr/src/initramfs として表していますが、前者を選択した場合(あなたが Custom Initramfs を使用しているのでなければ、通常はこちらです)、/path/to/my/initramfs/myinitrd.cpio.gz で置き換える必要があります。
General Setup --->
[*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
(/usr/src/initramfs) Initramfs source file(s)
すべて正しく機能していることを確認するには、カーネルを initrd コマンドライン引数を付けずに起動します。
バックアップカーネル
バックアップのカーネルを常に用意しておくことをおすすめします。grub はスタブカーネルを通常のカーネルと同様に起動することができるため、grub のようなブートマネージャーが既にインストールされているのであればそれをアンインストールしないようにしてください。2つめの選択肢は、予備の UEFI エントリを用意することです。新しいカーネルをインストールする前に、現在のものを /efi/EFI/example/ から /efi/EFI/backup へコピーしておきます。2つめの UEFI エントリも efibootmgr で作成しておきます。この例では、異なる名前が使用されています:
root #
efibootmgr
BootCurrent: 0002 Timeout: 1 seconds BootOrder: 0002,0000,0001 Boot0000* Secure HD(1,GPT,0adcbfee-21aa-42ea-9a9a-2e53bd05e6a2,0x800,0x7f800)/File(\EFI\secure\bzImage.efi) Boot0001* gentoo HD(1,GPT,0adcbfee-21aa-42ea-9a9a-2e53bd05e6a2,0x800,0x7f800)/File(\EFI\gentoo\grubx64.efi) Boot0002* Backup HD(1,GPT,0adcbfee-21aa-42ea-9a9a-2e53bd05e6a2,0x800,0x7f800)/File(\EFI\backup\bzImage.efi)
マイクロコードのロード
initramfs を使わないカーネルを使用する場合は、以下の記事に記載されているようにマイクロコードをロードすることが推奨されます:
省略可能: セキュアブートのために署名する
このカーネルをセキュアブートする場合は、app-crypt/sbsigntools に含まれる sbsign を使用して署名しなくてはなりません:
root #
sbsign --key {db key} --cert {db cert} /efi/EFI/example/bzImage.efi
さらなる情報が Secure Boot で確認できます。
通常の EFI スタブには必要な .sbat sbat セクションがないため、sys-boot/shim 経由で EFI スタブを起動することはできません。そのため、Secure Boot を有効にした状態で EFI スタブを起動するには、使用した署名鍵を UEFI ファームウェアで直接登録する必要があります。shim 経由での起動もサポートする EFI スタブの代替的な起動方法については、Unified Kernel Image のウィキページを参照してください。
トラブルシューティング
(U)EFI の実装によっては稀に、個別の EFI エントリを受け付けないことがあります。この場合はリムーバブルメディアパスを使用する方法がしばしば動作します。詳細については Efibootmgr #removable media を参照してください。例えば、このコマンドは64ビット UEFI 用のカーネルをコピーします:
root #
cp /usr/src/linux/arch/x86/boot/bzImage /efi/EFI/boot/bootx64.efi
- gcc:10 でコンパイルされた古いカーネルはブート時にクラッシュすることがありました (bug #721734#c4)。
- sys-kernel/gentoo-kernel-bin を使用している場合は、efibootmgr を使用して
root=
パラメータでルートパーティションパスを指定することができます:
root #
efibootmgr -c -L "Gentoo Linux" -l '\EFI\Gentoo\bootx64.efi' -u 'root=PARTUUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
- efibootmgr で、スワップパーティションへのハイバネーションに対応したブートエントリを作成するには:
root #
efibootmgr -c -L "Gentoo Linux" -l '\EFI\Gentoo\bootx64.efi' -u 'root=PARTUUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX resume=PARTUUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
関連項目
- UEFI — a firmware standard for boot ROM designed to provide a stable API for interacting with system hardware. On x86 it replaced the legacy BIOS.
- Efibootmgr — UEFI ブートエントリを管理するためのツールです。
- アーキテクチャ固有のカーネルコンフィグ (AMD64 ハンドブック)
- REFInd — rEFIt からフォークした後継の EFI および UEFI プラットフォーム向けブートマネージャ
- Unified Kernel Image — a single executable which can be booted directly from UEFI firmware, or automatically sourced by boot-loaders with little or no configuration.
外部資料
- EFI スタブに関する Linux カーネルドキュメンテーション
- EFI Stub - booting without a bootloader この記事は部分的にこのブログポストに基づいています。
- EFI bootloaders (U)EFI システムをブートする他の方法のリスト。
- Gentoo Forums: Suspend and Hibernate with UEFI
- http://www.kroah.com/log/blog/2013/09/02/booting-a-self-signed-linux-kernel/