EFI ブートスタブ

提供: ArchWiki
EFISTUBから転送)
ナビゲーションに移動 検索に移動

関連記事

EFI boot stub (別名:EFI stub) は、EFI 実行ファイルであるカーネルのことを指します。つまり、UEFI から直接起動できるカーネルのことです。

歴史的に、この記事や Debian Wiki では、この用語を一語で表現 (EFISTUB または EFIStub) としていました。

Arch Linux のカーネルはデフォルトで EFI ブートスタブです。もし カーネルをコンパイル する場合は、CONFIG_EFI_STUB=y を設定して有効化します。詳細については、The EFI Boot Stub を参照してください。

続行する前に、EFI システムパーティション を用意し、どのようにマウントするか選択 する必要があります。

ヒント:
  • ESP(EFIシステムパーティション)を /boot にマウントすれば、pacman が UEFI が読み取るカーネルを直接更新します。
  • EFIブートスタブは ブートローダー を介して間接的に起動することも可能です:
    • 複数のUEFIブートマネージャーが追加のオプションを提供したり、UEFIブートプロセスを簡略化したりすることができます。
    • これは、カーネルパラメータ を試したり、複数のカーネルや OS を使用したりする場合、またはマザーボードの UEFI ブートメニューが使いにくい場合に特に有用です。
    • カーネルと initramfs が存在するパーティションのファイルシステムドライバーを持つブートマネージャー(例: rEFInd)を使用すれば、これらを ESP の外に置くことが可能です。

EFISTUB の起動

ノート: カーネル EFI ブートスタブに渡される initramfs のパスは、EFI システムパーティション(ESP)のルートからの相対パスであり、EFI 規格に従ってバックスラッシュを使用する必要があります。例えば、initramfs が esp/EFI/arch/initramfs-linux.img にある場合、対応する UEFI 形式の行は initrd=\EFI\arch\initramfs-linux.img となります。以下の例では、すべてが esp/ 以下にあると仮定します。

UEFI を直接使う

UEFI は GRUB のような中間ブートローダを必要としないように設計されています。あなたのマザーボードに優れた UEFI 実装があれば、UEFI ブートエントリーにカーネルパラメータを埋め込んで、マザーボードが直接 Arch を起動させることができます。 efibootmgr や UEFI Shell v2 を使ってマザーボードのブートエントリーを変更することができます。

ノート:
  • 古い UEFI の実装は Linux カーネルとの互換性に問題がある場合があります。もしあなたの UEFI にバグフィックスが施された新しいバージョンがあるのなら、メーカー推奨のツールでフラッシュすることを検討してください。
  • NVRAM のブートエントリから EFI バイナリにコマンドラインパラメータを渡さないファームウェアもあります[1] この場合、カーネルとパラメータを Unified カーネルイメージ に統合して、できた .efi ファイルでブートエントリを作成することが可能です。

efibootmgr

カーネルをロードする efibootmgr を使用してブートエントリを作成するには:

# efibootmgr --create --disk /dev/sdX --part Y --label "Arch Linux" --loader /vmlinuz-linux --unicode 'root=block_device_identifier rw initrd=\initramfs-linux.img'

ここで、/dev/sdX は ESP(EFI システムパーティション)が存在するドライブを、Y はそのパーティション番号を指します。また、root=のパラメーターにはLinuxのルートパーティションを指定します。

ノート: サポートされているデバイス名の形式については カーネルパラメータ、対応する値の取得方法については 永続的なブロックデバイスの命名、および例については永続的なブロックデバイスの命名#カーネルパラメータ を参照してください。

省略された場合、/dev/sda の最初のパーティションが ESP として使用されます。

引用符内の -u/--unicode 引数は、単なる カーネルパラメータ のリストであるため、必要に応じて追加のパラメーターを指定する必要があります(例: ハイバネート先指定を initramfs に渡す)

LTS Linux カーネル、NVME ストレージ、特定のサブボリュームを備えた BTRFS ファイルシステム、およびスワップパーティションでの休止状態の例:

# efibootmgr --create \
 --disk /dev/nvme0n1 --part 1 \
 --label "EFISTUB Arch" \
 --loader /vmlinuz-linux-lts \
 --unicode 'root=UUID=01a40dd8-28f0-4636-be1e-aeed60c98095 resume=UUID=2d877d5d-4ca1-4d46-a3d6-b6ee94cbbd78 rw rootflags=subvol=@ loglevel=3 quiet initrd=\initramfs-linux-lts.img'

ブートエントリを使用してリストを取得したり、ブートの注文を設定したり、削除したりするには、efibootmgr を参照してください。

ヒント:
  • kesboot-gitAUR パッケージを使用すると、これを簡素化して自動化できます。このパッケージには、パッケージ操作中にEFI変数を追加および削除できる pacman フック も含まれています。
  • https://github.com/de-arl/auto-UEFI-entry は、コマンドを作成するための Bash ヘルパーです。
  • ブートエントリーを作成するコマンドをシェルスクリプトに保存しておくと、カーネルパラメーターを変更する場合などに簡単に修正できて便利です。この際、古いブートエントリーを削除する処理を自動化することを検討してください。現在のところ、efibootmgr既存のエントリーの編集をサポートしていません
  • フォーラム投稿 The linux kernel with build in bootloader? も参考になるかもしれません。

bcfg

UEFI の実装によっては efibootmgr を使って NVRAM をうまく変更することが難しいものがあります。efibootmgr がうまくエントリを作成できない場合、UEFI シェル v2 で bcfg コマンドを使うことができます (例:Arch Linux live iso から)

まず、あなたの ESP が存在するデバイス番号を調べます。

Shell> map

この例では、デバイス番号として 1 を使用しています。ESP の中身を一覧表示する。

sshell> ls FS1:

現在のブートエントリーを表示するには

Shell> bcfg boot dump

カーネルのエントリを追加するには、以下を使用します。

Shell> bcfg boot add N とします。FS1:\vmlinuz-linux "Arch Linux"

ここで N はブートメニューに追加されるエントリの場所です。0 は最初のメニュー項目です。既に存在するメニュー項目は、破棄されることなくメニュー内で移動されます。

ESP 上にファイルを作成し、必要なカーネルオプションを追加します。

Shell> FS1:\options.txt を編集します。

ファイル内に、ブートラインを追加します。たとえば、以下のようになります。

root=/dev/sda2 ro initrd=initramfs-linux.img
ノート: ファイル内の行頭に余分なスペースを入れてください。行頭には byte order mark があり、ブート時にエラーの原因となるその隣の文字を潰してしまいます。

保存するには F2 を、終了するには F3 を押してください。

前のエントリにこれらのオプションを追加します。

Shell> bcfg boot -opt N FS1:\options.txt

追加する項目がある場合は、この作業を繰り返してください。

前に追加した項目を削除するには、次のようにします。

Shell> bcfg boot rm N

kesboot

kesboot-gitAUR パッケージのスクリプトを使って EFISTUB での作業を単純化・自動化することもできます。パッケージの操作中に EFI 変数を追加・削除するための pacman フック も含まれています。

まず、パッケージをインストールして、/etc/kesboot.conf ファイルを設定します。

/etc/kesboot.conf
CMDLINES=('linux' 'acpi=on'
          'linux-zen' 'iommu=off')
ノート: フック (変数 INSTALL_HOOKREMOVE_HOOK) を使用すると、実行するたびに CMDLINES 配列を上書きします(すべてのレコードの内容を。

次に、以下を実行します。

# kesboot -u

また、本パッケージには EFI ブートの初期設定用のプログラムも含まれています。ESPのマウント ディレクトリの後、以下を実行してください。

# /usr/lib/setup-efi-boot

UEFI Shell を使う

通常の UEFI アプリケーションと同じように UEFI Shell から EFISTUB カーネルを起動できます。その場合、通常のパラメータとして起動する EFISTUB カーネルファイルにカーネルパラメータを渡してください:

> fs0:
> /vmlinuz-linux root=PARTUUID=3518bb68-d01e-45c9-b973-0b5d918aae96 rw initrd=/initramfs-linux.img

毎回カーネルパラメータを全て指定したくない場合、UEFI システムパーティションに archlinux.nsh などのシェルスクリプトの実行コマンドを保存することができます。以下のコマンドで起動できるようになります:

> fs0:
> archlinux

startup.nsh スクリプトの使用

いくつかの UEFI 実装はコールドブート間で EFI 変数を保持せず (例:VirtualBox バージョン 6.1 以前)、UEFI ファームウェアインターフェースを通して設定したものは電源切断時に失われてしまいます。

UEFI Shell Specification 2.0 は ESP パーティションのルートにある startup.nsh というスクリプトが常に解釈され、任意の命令を含むことができると定めています; その中でブートローディングラインを設定することが可能です。ESP パーティションを /boot にマウントし、カーネルブートローディングラインを含む startup.nsh スクリプトを作成することを確認します。例えば

vmlinuz-linux rw root=/dev/sdX [rootfs=myfs] [rootflags=myrootflags] \
 [kernel.flag=foo] [mymodule.flag=bar] \
 [initrd=\intel-ucode.img] initrd=\initramfs-linux.img

この方法は、実際のハードウェアで遭遇する可能性のあるほぼすべての UEFI ファームウェアバージョンで機能します。最後の手段として使用できます。 スクリプトは1つの長い行である必要があります。 括弧内のセクションはオプションであり、ガイドとしてのみ提供されています。シェルスタイルの改行は、視覚的にわかりやすくするためのものです。 FAT ファイルシステムはバックスラッシュをパス区切り文字として使用します。この場合、バックスラッシュは initramfs が ESP パーティションのルートにあることを宣言します。 Intel マイクロコードのみが起動パラメータ行にロードされます。 AMD マイクロコードは、後で起動プロセス中にディスクから読み取られます。これはカーネルによって自動的に行われます。

ヒントとテクニック

フォールバック RAM ディスクを使用したブートエントリ

ブートマネージャなしで EFISTUB を使用する場合、カーネルコマンドラインはブート時に変更できません。例えば initramfs-linux-fallback.img を使ったり、Intel マイクロコード無しで起動したりするような、少なくともある種のフォールバックの可能性を持つには、efibootmgr でさらなるブートエントリーを作成するだけです。

トラブルシューティング

EFISTUB はいくつかの Dell システムで動作しません

いくつかの世代の Dell ファームウェアは、ブートローダに渡す引数を間違えており、そのため EFISTUB は通常起動不可能なシステムを意味する null コマンドラインをパースします (linux-efi thread を参照してください)

Linux 5.10 からは、この挙動を修正する回避策が見つかっています (この commit を参照してください) Linux < 5.10 では、arch-efiboot のような efi-packer を使うか、別のブートローダを使うことができます。

ブートエントリーの変更が適用されない

Haswell 時代の Asus ボード(こちらのフォーラムを参照) などの一部のマザーボードは、システムが起動しない限りブートエントリの変更に気づきません。更新された EFISTUB エントリをブートする前に、別の既存のブート エントリを使用してください。

参照