From ArchWiki
Revision as of 10:04, 16 March 2014 by Jstjohn (talk | contribs) (remove needless attributes from wiki tables and/or use class="wikitable")
Jump to navigation Jump to search
Warning: カーネルバージョンとマザーボードのモデルによっては EFISTUB の起動が失敗するというバグが報告されています。詳しくは [1][2] を見て下さい。

Linux カーネル (linux>=3.3) は EFISTUB (EFI BOOT STUB) ブートをサポートしています。カーネル設定で CONFIG_EFI_STUB=y を設定することで有効にすることができ、Arch Linux のカーネルではデフォルトで有効にされています (詳しくは The EFI Boot Stub を参照してください)。

EFISTUB カーネルだけでは他のカーネルを起動することはできません。よってブートメニューエントリごとに EFISTUB カーネル + Initramfs のペアが必要です。このため、複数のカーネルを使う場合は、UEFI Boot Manager を使うことが推奨されています。


  1. EFI System Partition を作成してください。
  2. /boot (推奨) かどこか他の好きなところに (他のディストロやツールは大抵 /boot/efi を使っています) EFI System Partition をマウントしてください。以後このマウントポイントは $esp として示します。

カーネルと initramfs を ESP にコピーする

Warning: この手順は EFISYS のマウントポイントとして /boot を使っていない場合にのみ必要です。マウントポイントとして /boot を選んだ時は、#EFISTUB の起動 に進むことができます。
  1. $esp/EFI/arch/ を作成してください
  2. 以下のファイルを移動元から移動先にコピーしてください
ブートファイルの移動元 UEFI の移動先
/boot/vmlinuz-linux $esp/EFI/arch/vmlinuz-arch.efi
/boot/initramfs-linux.img $esp/EFI/arch/initramfs-arch.img
/boot/initramfs-linux-fallback.img $esp/EFI/arch/initramfs-arch-fallback.img
Warning: カーネルがアップデートされる度に EFISTUB カーネルを更新する必要があります。また、以下の方法のどれか一つを使うことで EFISTUB カーネルを自動で更新することができます:


Systemd にはイベントトリガータスク機能があります。これで、パス上の変更を検知する能力を使って、boot にある EFISTUB カーネルと initramfs のファイルが更新されたときにそれらを同期させることが可能です。

Warning: mkinitcpio がカーネルスタブと initramfs を作成するのには時間がかかるので、以下の systemd サービスが新しいカーネルスタブと initramfs の代わりに古いものをコピーしてしまう可能性があります。このエラーの可能性を減らすために、(mkinitcpio によって最後に作成される) initramfs-linux-fallback.img が更新されたか確認する efistub のコピーサービスをバインドすると良いでしょう。
Description=Copy EFISTUB Kernel to UEFISYS Partition


Description=Copy EFISTUB Kernel to UEFISYS Partition

ExecStart=/usr/bin/cp -f /boot/vmlinuz-linux $esp/EFI/arch/vmlinuz-arch.efi
ExecStart=/usr/bin/cp -f /boot/initramfs-linux.img $esp/EFI/arch/initramfs-arch.img
ExecStart=/usr/bin/cp -f /boot/initramfs-linux-fallback.img $esp/EFI/arch/initramfs-arch-fallback.img


# systemctl enable efistub-update.path


incron を使って更新後に EFISTUB カーネルを同期するスクリプトを実行することができます。

Tip: 下のスクリプトを /usr/local/bin/efistub-update.sh として保存してください
#!/usr/bin/env bash
/usr/bin/cp -f /boot/vmlinuz-linux $esp/EFI/arch/vmlinuz-arch.efi
/usr/bin/cp -f /boot/initramfs-linux.img $esp/EFI/arch/initramfs-arch.img
/usr/bin/cp -f /boot/initramfs-linux-fallback.img $esp/EFI/arch/initramfs-arch-fallback.img
Tip: 下のスクリプトを /etc/incron.d/efistub-update.conf として保存してください
Note: 最初のパラメータ /boot/initramfs-linux-fallback.img は監視するファイルです。2番目のパラメータ IN_CLOSE_WRITE は監視するイベントです。3番目のパラメータ /usr/local/bin/efistub-update.sh は起動するスクリプトです。
/boot/initramfs-linux-fallback.img IN_CLOSE_WRITE /usr/local/bin/efistub-update.sh
Tip: この方法を使うには、incron が有効になっている必要があります。有効になっていない場合は次を実行してください
# systemctl enable incrond.service

Mkinitcpio フック

Mkinitcpio はフックを生成することができシステムレベルデーモンを機能させる必要はありません。バックグラウンドプロセスを生成して vm-linuz, initramfs-linux.img, initramfs-linux-fallback.img の生成を待ち; そして #EFISTUB の設定 の手順4に従います。

Tip: 下のスクリプトを /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
Tip: 下のスクリプトを /root/watch.sh として保存し実行可能にしてください
#!/usr/bin/env bash

while [[ -d "/proc/$PPID" ]]; do
	sleep 1

/usr/bin/cp -f /boot/vmlinuz-linux $esp/EFI/arch/vmlinuz-arch.efi
/usr/bin/cp -f /boot/initramfs-linux.img $esp/EFI/arch/initramfs-arch.img
/usr/bin/cp -f /boot/initramfs-linux-fallback.img $esp/EFI/arch/initramfs-arch-fallback.img

echo "Synced kernel with ESP"
Tip: efistub-update/etc/mkinitcpio.conf 内の hook のリストに加えて下さい

/etc/fstab バインドマウント

  • The following method should work similarly with any distribution that does not symlink in /boot. See Warnings for caveats.
  • This involves no special scripts, services, or bootloader filesystem drivers.
  • This centralizes and organizes kernels and initrds across installations on one partition.
  • This avoids possible limitations imposed by firmware and/or the bootloader on boot device configuration as can often occur with RAID and/or LVM (excepting the standard FAT32 EFI system partition, of course).
  • Beyond initial configuration this should persist without special consideration or maintenance.
  • This should be transparent to any action normally affecting /boot and the files therein.
  • This requires both a kernel and a bootloader compatible with the FAT32 filesystem.
  • Because the FAT32 filesystem cannot handle symlinks, this will not behave as intended with an installation that requires them in /boot.
  • Initial configuration requires root level access.
  • This may require a large EFI system partition in order to accomodate multiple installations.
  • All kernels will require at least a root=system root parameter passed at boot.
  • per rEFInd's author: OpenSUSE definitely uses symbolic links in /boot... Fedora, Ubuntu, and ... OpenSUSE all refuse a FAT partition as /boot in ... setup [which] can be worked around [in] /etc/fstab. Forum post [here].
通常は EFI system partition を /boot/efi サブフォルダにマウントしますが、以下ではその逆を行います。
  • 他で記述されているように FAT32 フォーマットの ef00 タイプの EFI system partition を作成してください。
  • It may be beneficial to make it several gigabytes in size to accomodate multiple installations.
  • Use the GPT partition name feature for added convenience. For example name the partition esp.
  • マウントポイントを作成して EFI system partition をファイルシステムのどこかにマウントしてください。例:
$ mkdir /esp
$ mount -L esp /esp
  • システムの /boot ファイルを含めるため、EFI system parition の /EFI/boot にフォルダを作成してください。例:
$ mkdir /esp/EFI/boot/arch64-laptop
  • The refind bootloader automatically detects and adds EFI loadable kernel files installed to the EFI system partition in /EFI/boot/*/ by default.
  • Keying F2 on a highlighted refind boot menu entry enables adding the required root= kernel parameter to an auto-added or otherwise unconfigured menu entry.
  • /boot にある全てのファイルを削除して EFI system partition に新しくフォルダを作成します。例:
$ mv /boot/* /esp/EFI/boot/arch64-laptop/
  • EFI system partition に新しく生成したフォルダを /boot にバインドマウントしてください。例:
$ mount --bind /esp/EFI/boot/arch64-laptop /boot
  • $ ls /boot/ でファイルが大丈夫か確認してから、/etc/fstab を編集して変更を永続的にしてください。例:
LABEL=arch64-laptop_rootfs / ext4 defaults 0 0
LABEL=esp /esp vfat defaults 0 0
/esp/EFI/boot/arch64-laptop /boot none defaults,bind 0 0
  • 必要に応じて root= カーネルブートパラメータを適用するようにブートローダを更新してください。例:
... root=LABEL=arch64-laptop_rootfs ...
Note: refind-efi 0.2.7 現在、refind は /boot にあるカーネルを自動で検知します。名前を変更して .efi 拡張子を付ける必要はありません。そのため、同期スクリプトは refind を使うなら必要ありません。ただし、カーネルが保存されている Linux のファイルシステムを読み込むために EFI ドライバーをインストールしなくてはなりません。


Warning: Linux Kernel EFISTUB initramfs のパスは EFI System Partition のルートからの相対パスでなければなりません。例えば、initramfs が $esp/EFI/arch/initramfs-linux.img にあったとしたら、適切な UEFI 行は initrd=/EFI/arch/initramfs-linux.imginitrd=\EFI\arch\initramfs-linux.img になります。

以下の方法のどれか一つを使うことで EFISTUB カーネルを起動することができます:

gummiboot を使う

Gummiboot は EFISTUB カーネルのナイスなメニューを提供する UEFI Boot Manager です。gummiboot として [core] から利用でき、EFISTUB ブートの推奨ブートマネージャです。詳細は gummiboot を見て下さい。

rEFInd を使う

rEFInd は (Intel Mac で使われている) rEFIt Boot Manager の Rod Smith (GPT-fdisk の作者) によるフォークです。rEFInd は Mac 以外の UEFI ブートについて rEFIt の多くの問題を修正してあり EFISTUB カーネルをサポートしています。

Tip: もし EFISTUB や rEFInd を初めて知ったのなら、先に進む前に The rEFInd Boot Manager: Methods of Booting Linux を読んで下さい。このセクションはひとつのユースケースを説明しているだけであり全ての設定に適しているというわけではありません。
Note: refind-efi には上流からのインストールスクリプト /usr/bin/refind-install が含まれており、上の手順と同じように rEFInd の設定を行います。
Note: 32ビットの IA32 EFI を使っている場合、下のコマンドにある x64ia32 に置き換えてください (大文字小文字を区別します)。
  • efivarfs をマウントしてください
# mount -t efivarfs efivarfs /sys/firmware/efi/efivars              # ignore if already mounted
  • refind-efi パッケージをインストールしてください
# pacman -S refind-efi
  • 以下のファイルをコピーしてください
# cp /usr/share/refind/refind_x64.efi $esp/EFI/refind/refind_x64.efi
# cp /usr/share/refind/refind.conf-sample  $esp/EFI/refind/refind.conf
# cp -r /usr/share/refind/icons $esp/EFI/refind/icons
# cp -r /usr/share/refind/drivers_x64 $esp/EFI/refind/drivers
  • rEFInd の設定ファイルは $esp/EFI/refind/refind.conf です。このファイルには注釈が沢山つけられています。
  • カーネルと initramfs ファイルが置かれているディレクトリの中に refind_linux.conf ファイルを作成してください。
"Boot with defaults" "root=PARTUUID=3518bb68-d01e-45c9-b973-0b5d918aae96 rw rootfstype=ext4 add_efi_memmap systemd.unit=graphical.target"
"Boot to Terminal"   "root=PARTUUID=3518bb68-d01e-45c9-b973-0b5d918aae96 rw rootfstype=ext4 add_efi_memmap systemd.unit=multi-user.target"
Tip: refind_linux.conf のそれぞれの行は rEFInd によってサブメニューとして表示されます。サブメニューは "+" や "insert" キーで開けます。
Note: Replace the string after PARTUUID with your root's PARTUUID. Please note in the example above that PARTUUID/PARTLABEL identifies a GPT partition, and differs from UUID/LABEL, which identifies a filesystem. Using the PARTUUID/PARTLABEL is advantageous because it is invariant if you reformat the partition with another filesystem. It's also useful if you don't have a filesystem on the partition (or use LUKS, which doesn't support LABELs).
  • efibootmgr を使って UEFI ブートメニューにブートエントリを作成してください
# efibootmgr -c -d /dev/sdX -p Y -l /EFI/refind/refind_x64.efi -L "rEFInd"
Note: refind-efi 0.2.7 より、refind は /boot にあるカーネルを自動検知できます。これには /boot パーティション (/boot が分割されていない場合は / パーティション) で使われているファイルシステムの UEFI ドライバが ESP 内に存在し、rEFInd によってロードされている必要があります。refind.conf のデフォルト設定で有効にされています (ESP にあるドライバのフォルダを記述する必要はあるかもしれません)。詳しくは [3] を見て下さい

Systemd による自動化

以下のスクリプトを使うことで、refind ファイルのコピーと (必要ならば) nvram の更新を自動化することができます。

Note: UEFISYS パーティションで refind をインストールするディレクトリを変更したい場合は、スクリプトの中の $refind_dir の値を変更してください。
#!/usr/bin/env bash
## COPYRIGHT 2013 : MARK E. LEE (BLUERIDER) : mlee24@binghamton.edu; mark@markelee.com

## LOG
## 1/17/2013 : Version 2 of refind_name_patch is released
##           : Supports long subdirectory location for refind
##           : Updates nvram when needed
##           : 10% speed boost
## 7/15/2013 : Changed arch to match 32-bit (ia32) and 64-bit (x64) naming scheme
##           : Changed directory copying in update-efi-dir to copy tools and drivers directories explicitly
##           : Changed efibootmgr writing code to be more concise and added (-w) to write the entry as per dusktreader's excellent guide : https://docs.google.com/document/d/1pvgm3BprpXoadsQi38FxqMOCUZhcSqFhZ26FZBkmn9I/edit
##           : Function to check if NVRAM boot entry was already listed was fixed to use awk and an if then clause
##           : ref_bin_escape was modified from : ref_bin_escape=${ref_bin//\//\\\\} to remove extra backslashes (error does not show up when using cmdline)
## 7/29/2013 : Changed location of tools,drivers, and binary directory to match capricious upstream move to /usr/share/refind

function main () {  ## main insertion function
  declare -r refind_dir="/boot/efi/EFI/refind"; ## set the refind directory
  arch=$(uname -m | awk -F'_' '{if ($1 == "x86") {print "x"$2} else if ($1 == "i686") {print "ia32"}}') &&  ## get bit architecture
  update-efi-dir;  ## updates or creates the refind directory
  update-efi-nvram;  ## updates nvram if needed

function update-efi-dir () {  ## setup the refind directory
  if [ ! -d $refind_dir ]; then  ## check if refind directory exists
    echo "Couldn't find $refind_dir";
    mkdir $refind_dir &&  ## make the refind directory if needed
    echo "Made $refind_dir";
  if [ "$arch" ]; then  ## check if anything was stored in $arch
    cp -r /usr/share/refind/{refind_$arch.efi,keys,images,icons,fonts,docs,{tools,drivers}_$arch} $refind_dir/  && ## update the bins and dirs
    echo "Updated binaries and directory files for refind at $refind_dir";
    echo "Failed to detect an x86 architecture";

function update-efi-nvram () { ## update the nvram with efibootmgr
  declare -r ref_bin=${refind_dir/\/boot\/efi}/refind_$arch.efi;  ## get path of refind binary (without /boot/efi)
  declare -r ref_bin_escape=${ref_bin//\//\\};  ## insert escape characters into $ref_bin
  [ "$(efibootmgr -v | awk "/${ref_bin_escape//\\/\\\\}/")" ] && ( ## check if boot entry is in nvram \
    echo "Found boot entry, no need to update nvram";
    ) || ( ## if boot entry is not in nvram; add it
    declare -r esp=$(mount -l | awk '/ESP/ {print $1}') &&  ## get ESP partition
    efibootmgr -cgw -d ${esp:0:8} -p ${esp:8} -L "rEFInd" -l $ref_bin_escape && ## update nvram
    echo "
    Updated nvram with entry rEFInd to boot $ref_bin
    Did not copy configuration files, please move refind.conf to $refind_dir/";
main;  ## run the main insertion function
Note: refind-efi 0.2.7 より、refind は /boot にあるカーネルを自動で検知します。名前を変更して .efi 拡張子を付ける必要はありません。そのため、以下の同期スクリプトは refind を使うなら必要ありません。ただし、カーネルが保存されている Linux のファイルシステムを読み込むために EFI ドライバーをインストールしなくてはなりません。
Description=Update rEFInd bootloader files


Description=Update rEFInd directories, binaries, and nvram

ExecStart=/usr/bin/bash /usr/lib/systemd/scripts/refind_name_patchv2
Tip: 次を実行して systemd の path ユニットを有効にしてください:
# systemctl enable refind_update.path

Apple Macs

Apple Mac の場合、Linux 用の実験的な "bless" ユーティリティが含まれている mactel-bootAUR を試して下さい。これが動作しないときは、OSX の中から "bless" を使って rEFInd をデフォルトのブートローダに設定してください。OSX の中で UEFISYS パーティションが /mnt/efi にマウントされているとして、次を実行します:

$ sudo bless --setBoot --folder /mnt/efi/EFI/refind --file /mnt/efi/EFI/refind/refind_x64.efi


VirtualBox の場合については、VirtualBox (日本語)#Virtualbox の EFI モードで Arch を使う を参照してください。

UEFI Shell を使う

通常の UEFI アプリケーションのように UEFI Shell から EFISTUB カーネルを起動することが可能です。この場合カーネルパラメータは通常のパラメータとして起動する EFISTUB カーネルファイルに渡します。

> fs0:
> cd \EFI\arch
> vmlinuz-arch.efi root=PARTUUID=3518bb68-d01e-45c9-b973-0b5d918aae96 ro rootfstype=ext4 add_efi_memmap initrd=EFI/arch/initramfs-arch.img

また、ブートパラメータを記述したシンプルな archlinux.nsh ファイルを書いて UEFI System Partition に置き、それを実行することもできます:



echo -on
\EFI\arch\vmlinuz-arch.efi root=PARTUUID=3518bb68-d01e-45c9-b973-0b5d918aae96 rootfstype=ext4 add_efi_memmap initrd=/EFI/arch/initramfs-arch.img

この方法では名前をメモしておいたり20-30文字も入力せずとも UUID を指定することができます。

efibootmgr エントリを使って直接起動する

Warning: カーネルと efibootmgr の組み合わせによっては手動で調整しないと動かないことがあります [4]。ブートエントリを削除することはできますが作成することは出来なくなります。
Note: UEFI ファームウェアによってはブートエントリの uefi アプリケーションにコマンドラインパラメータを埋め込むことができません。

efibootmgr によって作成したブートエントリに直接カーネルパラメータを埋め込むことが可能です。つまりあなたの UEFI ブートオーダー・GUI を使って GRUB など他のブートローダーを使わずに直接 Arch Linux を起動することができます (下のコマンドで、EFI System Partition は /dev/sdX 上に、パーティションは Y にあると仮定しています)。

# mount -t efivarfs efivarfs /sys/firmware/efi/efivars              # 既にマウントされている場合は無視して下さい
# efibootmgr -c -d /dev/sdX -p Y -l /EFI/arch/vmlinuz-arch.efi -L "Arch Linux (EFISTUB)" -u "$(cat /proc/cmdline)"


# efibootmgr -v

また、ブートオプションの順番を新しく割り当てて (efibootmgr -o) Arch のエントリを最後に持ってくることで、失敗した時にシステムが楽にリカバーできます。

Tip: シェルスクリプトでブートエントリを作成するコマンドをどこかに保存しておけば、修正 (例えばカーネルパラメータの変更) が楽になります。

efibootmgr の詳細は UEFI#efibootmgr で説明しています。フォーラムの投稿 https://bbs.archlinux.org/viewtopic.php?pid=1090040#p1090040