EFI ブートスタブ
Linux カーネルは EFISTUB ブートをサポートしており、EFI ファームウェアがカーネルを EFI 実行可能ファイルとしてロードできるようにします。このオプションは、Arch Linux カーネルではデフォルトで有効になっています。カーネルをコンパイルする場合は、カーネル構成で CONFIG_EFI_STUB=yを設定することでアクティブにできます。詳細については、EFI BootStub を参照してください。
目次
EFISTUB の設定
EFI システムパーティションを作成したら、システムパーティションをマウントする方法を選択してください。一番簡単なのは /boot にマウントするか /boot にバインドマウントすることです。pacman が直接 EFI ファームウェアによって読み込まれるカーネルを更新してくれます。その場合、#EFISTUB の起動に進んでください。
他の ESP マウントポイント
EFI システムパーティションを /boot にマウントしない場合、ブートファイルをコピーする必要があります (以下 EFI システムパーティションの場所を esp とします):
# mkdir -p esp/EFI/arch # cp /boot/vmlinuz-linux esp/EFI/arch/vmlinuz-linux # cp /boot/initramfs-linux.img esp/EFI/arch/initramfs-linux.img # cp /boot/initramfs-linux-fallback.img esp/EFI/arch/initramfs-linux-fallback.img
さらに、カーネルのアップデートがあったときに ESP のファイルを更新する必要があります。更新しないとシステムが起動できなくなってしまいます。以下のセクションでは自動でコピーする方法を説明しています。
systemd を使う
Systemd には特定のイベントが起こったときにタスクを実行する機能があります。/boot が更新されたときに特定のパスにおける変更を検知して EFISTUB カーネルと initramfs ファイルを同期してください:
/etc/systemd/system/efistub-update.path
[Unit] Description=Copy EFISTUB Kernel to UEFISYS Partition [Path] PathChanged=/boot/initramfs-linux-fallback.img [Install] WantedBy=multi-user.target WantedBy=system-update.target
/etc/systemd/system/efistub-update.service
[Unit] Description=Copy EFISTUB Kernel to UEFISYS Partition [Service] Type=oneshot ExecStart=/usr/bin/cp -f /boot/vmlinuz-linux esp/EFI/arch/vmlinuz-linux ExecStart=/usr/bin/cp -f /boot/initramfs-linux.img esp/EFI/arch/initramfs-linux.img ExecStart=/usr/bin/cp -f /boot/initramfs-linux-fallback.img esp/EFI/arch/initramfs-linux-fallback.img
ユニットを作成したら efistub-update.path を起動・有効化してください。
incron を使う
incron を使うことでカーネルの更新時に EFISTUB カーネルを同期させるスクリプトを実行できます。
/usr/local/bin/efistub-update.sh
#!/usr/bin/env bash /usr/bin/cp -f /boot/vmlinuz-linux esp/EFI/arch/vmlinuz-linux /usr/bin/cp -f /boot/initramfs-linux.img esp/EFI/arch/initramfs-linux.img /usr/bin/cp -f /boot/initramfs-linux-fallback.img esp/EFI/arch/initramfs-linux-fallback.img
/etc/incron.d/efistub-update.conf
/boot/initramfs-linux-fallback.img IN_CLOSE_WRITE /usr/local/bin/efistub-update.sh
この方法を使う場合、incrond のサービスを有効にしてください:
# systemctl enable incrond.service
mkinitcpio フックを使う
Mkinitcpio はフックを生成することができ、システムレベルのデーモンを必要としません。バックグラウンドプロセスが生成され vm-linuz, initramfs-linux.img, initramfs-linux-fallback.img が生成されてからファイルをコピーします。
/etc/mkinitcpio.conf のフックのリストに efistub-update を追加してください。
/usr/lib/initcpio/install/efistub-update
#!/usr/bin/env bash
build() {
/root/watch.sh &
}
help() {
cat <<HELPEOF
This hook waits for mkinitcpio to finish and copies the finished ramdisk and kernel to the ESP
HELPEOF
}
/root/watch.sh
#!/usr/bin/env bash while [[ -d "/proc/$PPID" ]]; do sleep 1 done /usr/bin/cp -f /boot/vmlinuz-linux esp/EFI/arch/vmlinuz-linux /usr/bin/cp -f /boot/initramfs-linux.img esp/EFI/arch/initramfs-linux.img /usr/bin/cp -f /boot/initramfs-linux-fallback.img esp/EFI/arch/initramfs-linux-fallback.img echo "Synced kernel with ESP"
mkinitcpio フックを使う (別の方法)
上記の方法と別に、コピー操作を減らす方法があります。逆転の発想で initramfs を /boot ではなく EFI パーティションに直接保存します。そして mkinitcpio フックを使ってカーネルなどのファイルを ESP にコピーします。
/etc/mkinitcpio.d/linux.preset ファイルを編集してください:
/etc/mkinitcpio.d/linux.preset
# mkinitcpio preset file for the 'linux' package
# Directory to copy the kernel, the initramfs...
ESP_DIR="/boot/efi/EFI/arch"
ALL_config="/etc/mkinitcpio.conf"
ALL_kver="/boot/vmlinuz-linux"
PRESETS=('default' 'fallback')
#default_config="/etc/mkinitcpio.conf"
default_image="${ESP_DIR}/initramfs-linux.img"
default_options="-A esp-update-linux"
#fallback_config="/etc/mkinitcpio.conf"
fallback_image="${ESP_DIR}/initramfs-linux-fallback.img"
fallback_options="-S autodetect"
そして /usr/lib/initcpio/install/esp-update-linux ファイルを作成して実行可能属性を付与してください:
/usr/lib/initcpio/install/esp-update-linux
# Directory to copy the kernel, the initramfs...
ESP_DIR="/boot/efi/EFI/arch"
build() {
cp /boot/vmlinuz-linux "${ESP_DIR}/vmlinuz-linux.efi"
# If ucode is used uncomment this line
#cp /boot/intel-ucode.img "${ESP_DIR}/"
}
help() {
cat <<HELPEOF
This hook copies the kernel to the ESP partition
HELPEOF
}
テストするには以下のコマンドを実行:
# rm /boot/initramfs-linux-fallback.img # rm /boot/initramfs-linux.img # mkinitcpio -p linux
EFISTUB の起動
ブートマネージャを使う
UEFI ブートマネージャには UEFI ブートを簡単にすることができるオプションが存在します (特に複数のカーネルやオペレーティングシステムをインストールしている場合)。詳しくはブートローダーを見てください。
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
UEFI を直接使う
UEFI は GRUB などの中間的なブートローダーを排除できるように設計されています。使用しているマザーボードの UEFI 実装に問題がなければ、カーネルパラメータを UEFI ブートエントリの中に埋め込んでマザーボードから Arch を直接起動できます。efibootmgr や UEFI Shell v2 を使ってマザーボードのブートエントリを編集できます。
efibootmgr
以下のようなコマンドを実行してください:
# efibootmgr -d /dev/sdX -p Y -c -L "Arch Linux" -l /vmlinuz-linux -u "root=/dev/sdBZ rw initrd=/initramfs-linux.img"
/dev/sdX と Y は ESP が存在するディスクとパーティションに置き換えてください。root= パラメータを変更することで Linux のルートパーティションを指定できます (ディスクの UUID を使うこともできます)。-u 引数をダブルクオーテーションで囲っているのはカーネルパラメータを指定するためであり、ハイバネートやマイクロコードを使う場合はパラメータを追加する必要があります。
以下のコマンドを実行することで作成したエントリが問題ないか確認できます:
# efibootmgr -v
ブートの順序を設定するには、次のコマンドを実行:
# efibootmgr -o XXXX,XXXX
XXXX は `efibootmgr` コマンドの出力で確認できるエントリの数字に置き換えてください。
efibootmgr については UEFI#efibootmgr を見てください。https://bbs.archlinux.org/viewtopic.php?pid=1090040#p1090040 も参照。
UEFI Shell
UEFI の実装によっては efibootmgr を使用して NVRAM を編集できないことがあります。efibootmgr でエントリを作成できない場合、UEFI Shell v2 の bcfg コマンドを使用する方法があります。
カーネルのエントリを追加するには、以下を実行:
Shell> bcfg boot add N fsV:\vmlinuz-linux "Arch Linux"
N はエントリの優先度 (0 が一番優先されます) に、V は EFI パーティションのボリューム番号に置き換えてください。ボリューム番号がわからない場合、map コマンドを使うことでファイルシステムが確認できるので、ls コマンドで中身を確認してください:
Shell> map Shell> ls fs0:
最低限必要なカーネルオプションだけを追加する場合:
Shell> bcfg boot -opt N "root=/dev/sdX# rw initrd=\initramfs-linux.img"
N は優先度に /dev/sdX# はルートパーティションに置き換えてください。