EFI システムパーティション
EFI System Partition (ESP とも呼ばれます) は UEFI ファームウェアによって起動される UEFI ブートローダ、アプリケーション、ドライバの格納場所として機能する OS に依存しないパーティションです。UEFI ブートには必須です。
既存のパーティションの確認
例えば Windows 10 のようなオペレーティングシステムがインストールされている UEFI 対応のコンピュータに Arch Linux をインストールする場合、既に EFI システムパーティションがある可能性が非常に高いと言えます。
ディスクパーティションスキームとシステムパーティションを調べるには、起動したいディスクの root で fdisk を使用します:
# fdisk -l /dev/sdx
このコマンドは以下を返します。
- ディスクのパーティションテーブル:パーティションテーブルが GPT の場合は
Disklabel type: gpt
を、MBR の場合はDisklabel type: dos
を示します。 - ディスク上のパーティションのリスト:EFIシステムパーティションは通常100MiB以上の大きさで、タイプは
EFI System
またはEFI (FAT-12/16/32)
になっています。これが ESP であることを確認するには、ESP をマウントし、EFI
という名前のディレクトリがあるかどうかをチェックします。
既存の EFI システムパーティションが見つかった場合は、#パーティションのマウントに進んでください。見つからなかった場合はパーティションを作成する必要があります。#パーティションの作成に進んでください。
パーティションの作成
以下のセクションでは EFI System Partition (ESP) を作成する方法を説明しています。
ESP のサイズは、起動に必要なファイルとブートローダを格納するために十分な大きさである必要があります。
複数のカーネルや複数の unified カーネルイメージ、ブートローダー、ファームウェアのアップデートファイル、他のオペレーティングシステムのファイル、OEM のファイルを格納するのに十分なスペースを確保するために、ESP のサイズは 1 GiB にすることが推奨されます。これでも十分であるか疑問である場合は、4 GiB を割り当てておけばいかなる場合でも十分であるはずです。
GPT でパーティションされたディスク
GUID パーティションテーブル上の EFI システムパーティションはパーティションタイプ GUID C12A7328-F81F-11D2-BA4B-00A0C93EC93B
で識別されます。
GPT でパーティションされたディスクに ESP を作成する場合、以下の方法の一つを使って下さい:
- fdisk: パーティションを1つ作成し、
t
コマンドでパーティションタイプをEFI System
に変更してください。 - gdisk: パーティションタイプ
EF00
のパーティションを作成してください。 - GNU Parted: ファイルシステム
fat32
のパーティションを作成し、esp
フラグをセットしてください。
パーティション作成後、ファイルシステムでフォーマットする必要があります。以下の #パーティションのマウント セクションに従ってください。
MBR でパーティションされたディスク
Master Boot Record パーティションテーブル上の EFI システムパーティションは パーティションタイプ ID EF
により識別されます。
MBR でパーティションされたディスクに ESP を作成する場合、以下の方法の一つを使って下さい:
- fdisk: パーティションを1つ作成し、
t
コマンドでパーティションタイプをEFI (FAT-12/16/32)
に変更してください。 - GNU Parted: ファイルシステム
fat32
のプライマリパーティションを作成し、esp
フラグをセットしてください。
パーティション作成後、ファイルシステムでフォーマットする必要があります。以下の #パーティションのマウント セクションに従ってください。
パーティションのフォーマット
UEFI 仕様は FAT12、FAT16、FAT32 ファイルシステムのサポートを義務付けています(UEFI specification version 2.10, section 13.3.1.1) を参照)。しかし、準拠したベンダーは任意で追加のファイルシステムをサポートできます。例えば、Apple Mac のファームウェアは HFS+ ファイルシステムをサポートします。
他のオペレーティングシステムとの潜在的な問題を回避するために、また UEFI 仕様では UEFI は「システムパーティションに FAT32、リームバブルメディアに FAT12 と FAT16 の使用を包含する」[5]とあるので、FAT32 を使用することが推奨されます。dosfstools の mkfs.fat(8) ユーティリティを使用してください:
# mkfs.fat -F 32 /dev/sdxY
WARNING: Not enough clusters for a 32 bit FAT!
というメッセージが表示され、大きい ESP を作成できない場合、mkfs.fat -s2 -F32 ...
や -s1
でクラスタのサイズを減らしてください。さもないと、パーティションは UEFI によって読み込めません。サポートされるクラスタサイズは mkfs.fat(8) を見てください。
32 MiB よりも小さいパーティションでは、FAT32 を使うことはできません。この場合、FAT16 か FAT12 でフォーマットしてください。例えば、2 MiB の ESP は FAT12 しかサポートできません:
# mkfs.fat -F 12 /dev/sdxY
パーティションのマウント
システムの起動に成功するには、カーネル、initramfs ファイル、そして殆どの場合プロセッサのマイクロコードは、ブートローダーか UEFI それ自体からアクセスできる必要があります。なので、セットアップをシンプルにしたい場合、EFI システムパーティションのマウントポイントはブートローダの選択により制限されます。
典型的なマウントポイント
EFI システムパーティションのマウントに関しては、3つの典型的なシナリオがあります:
- ESP を
/boot
にマウントする:- システムのメンテナンスと管理が容易になります。
/boot
は、マイクロコードのパッケージが CPU のマイクロコード initramfs ファイルを配置し、mkinitcpio がカーネルと initramfs イメージを配置するデフォルトのパスだからです。 - 上記のファイルがほとんどのブートローダーからアクセスできることを保証できます。というのも、すべてのブートローダーが他のボリューム上のファイルにアクセスできるわけではないからです。
- この方法では、各ファイルに対してパーミッションや拡張属性を設定できません。FAT ファイルシステムはグローバルなパーミッションをマウント時に設定するからです。
- この方法では、ESP のサイズ要件が大きくなります。EFI 関連のファイルに加えて、通常
/boot
にインストールされるファイルが加わるからです。 - この方法では、デュアルブートの場合に OS 固有のブートファイルを他の OS からの潜在的に危険な操作に晒してしまいます。
- この方法では、/boot の暗号化が不可能です。EFI 関連のファイルはファームウェアからアクセス可能でなければならないからです。
- システムのメンテナンスと管理が容易になります。
- ESP を
/efi
にマウントする:- OS 関連のファイルと EFI 関連のファイルの懸念事項が分離されます。これらのファイルには他の OS のファイルが含まれている場合があり、放っておいたほうが良いでしょう。
/boot
にインストールされるファイルが ESP に入らないので、ESP のサイズ要件が大きくなってしまうことを防ぐことができます。EFI バイナリ (ブートローダ (とオプションでドライバ) や unified カーネルイメージ) のみが ESP に格納されることになるので、ストレージスペースを節約できます。/boot
内のファイルに Linux 固有のファイルシステムのパーミッションを保持することができ、FAT の制限に悩まされることはありません。- 必要に応じて ESP を別途マウントできます。例えば、ブートローダーをアップグレードするときにだけマウントするなどができます。
- 適切なセットアップでシステムの暗号化を行っている場合、
/boot
は保護される一方、いくつかの必要なファイルは暗号化されていない状態にできます。これは、他の場所に保存されているカーネルやファイルにアクセスできるファイルシステムドライバを持っている ブートローダーや unified カーネルイメージを使用する場合に便利です。
- ESP を
/efi
にマウントし、さらに "Extended Boot Loader Partition" (XBOOTLDR) を/boot
にマウントする。これは、先に作成しておいた ESP が、複数のブートローダーやカーネルを保存するには小さすぎるが、ESP を容易には拡張できない場合に便利です (そのような場合として、デュアルブートするために Windows のあとに Linux をインストールした場合などがあります)。この方法は、少なくとも systemd-boot によってサポートされています。
代替のマウントポイント
#典型的なマウントポイント を使わない場合、ブートファイルを ESP にコピーする必要があります(以後、ESP は esp
と表記します)。
# mkdir -p esp/EFI/arch # cp -a /boot/vmlinuz-linux esp/EFI/arch/ # cp -a /boot/initramfs-linux.img esp/EFI/arch/ # cp -a /boot/initramfs-linux-fallback.img esp/EFI/arch/
さらに、今後のカーネルアップデートの際に ESP 上のファイルを最新に保つ必要があります。これに失敗するとシステムが起動不能になる可能性があります。以下のセクションでは、これを自動化する方法をいくつか説明しています。
バインドマウントを使う
ESP を /boot
にマウントする代わりに、バインドマウントを使うことで ESP のディレクトリを /boot
にマウントすることができます (mount(8)
を参照)。これによって ESP を自由に扱えるようにしつつ pacman が直接カーネルを更新できるようにすることができます。ファイルをコピーする他の方法よりもずっとシンプルな方法になります。
#代替のマウントポイントに書かれているように、ESP のディレクトリに全てのブートファイルをコピーしますが、ESP は /boot
の外にマウントします。そしてディレクトリをバインドマウントします:
# mount --bind esp/EFI/arch /boot
これがうまく行ったことを確認したら、fstab を編集して永続化させます:
/etc/fstab
esp/EFI/arch /boot none defaults,bind 0 0
systemd を使う
systemd はイベントトリガーのタスクを特徴としています。この場合特に、パス内の変更を検出する機能は、/boot/
内で EFISTUB カーネルと initramfs ファイルがアップデートされたときにそれらを同期するのに使用されます。変更を監視するファイルは initramfs-linux-fallback.img
です。なぜなら、このファイルは mkinitcpio により最後にビルドされるからです。なので、このファイルを監視すれば、コピーを開始する前にすべてのファイルがビルド済みであることを保証できます。作成する systemd パスとサービスファイルは:
/etc/systemd/system/efistub-update.path
[Unit] Description=Copy EFISTUB Kernel to EFI system 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 EFI system partition [Service] Type=oneshot ExecStart=/usr/bin/cp -af /boot/vmlinuz-linux esp/EFI/arch/ ExecStart=/usr/bin/cp -af /boot/initramfs-linux.img esp/EFI/arch/ ExecStart=/usr/bin/cp -af /boot/initramfs-linux-fallback.img esp/EFI/arch/
作成後、efistub-update.path
を有効化・起動してください。
ファイルシステムイベントを使う
ファイルシステムイベントは、カーネルのアップデート後に EFISTUB カーネルを同期させるスクリプトを実行するのに利用できます。以下は incron を使った例です。
/usr/local/bin/efistub-update
#!/bin/sh cp -af /boot/vmlinuz-linux esp/EFI/arch/ cp -af /boot/initramfs-linux.img esp/EFI/arch/ cp -af /boot/initramfs-linux-fallback.img esp/EFI/arch/
/etc/incron.d/efistub-update.conf
/boot/initramfs-linux-fallback.img IN_CLOSE_WRITE /usr/local/bin/efistub-update
この方法を使うには、incrond.service
を有効化してください。
mkinitcpio フックを使う
Mkinitcpio はシステムレベルのデーモンを必要としないフックを生成できます。コピーする前に vmlinuz
、initramfs-linux.img
、initramfs-linux-fallback.img
の生成を待機するバックグラウンドプロセスを生成します。
/etc/mkinitcpio.conf
内のフックのリストに efistub-update
を追加してください。
/etc/initcpio/install/efistub-update
#!/usr/bin/env bash build() { /usr/local/bin/efistub-copy $$ & } help() { cat <<HELPEOF This hook waits for mkinitcpio to finish and copies the finished ramdisk and kernel to the ESP HELPEOF }
/usr/local/bin/efistub-copy
#!/bin/sh if [ "$1" -gt 0 ] then while [ -e /proc/"$1" ] do sleep .5 done fi rsync -a /boot/ esp/ echo "Synced /boot with ESP"
mkinitcpio プリセットを使う
/etc/mkinitcpio.d/
内のプリセットはシェルスクリプトをサポートするので、カーネルと initramfs は、そのプリセットを編集するだけでコピーできます。
上記の mkinitcpio フックを置き換える
/etc/mkinitcpio.d/linux.preset
ファイルを編集してください:
/etc/mkinitcpio.d/linux.preset
# mkinitcpio preset file for the 'linux' package # Directory to install the kernel, the initramfs... ESP_DIR="esp/EFI/arch" #ALL_config="/etc/mkinitcpio.conf" ALL_kver="${ESP_DIR}/vmlinuz-linux" PRESETS=('default' 'fallback') #default_config="/etc/mkinitcpio.conf" default_image="${ESP_DIR}/initramfs-linux.img" default_options="" #fallback_config="/etc/mkinitcpio.conf" fallback_image="${ESP_DIR}/initramfs-linux-fallback.img" fallback_options="-S autodetect"
テストするには以下を実行してください:
# rm /boot/initramfs-linux-fallback.img /boot/initramfs-linux.img # mv /boot/vmlinuz-linux esp/EFI/arch/ # mkinitcpio -p linux
もう一つの例
/etc/mkinitcpio.d/linux.preset
ESP_DIR="esp/EFI/arch" #ALL_config="/etc/mkinitcpio.conf" ALL_kver="$ESP_DIR/vmlinuz-linux$suffix" PRESETS=('default') default_config="/etc/mkinitcpio.conf" default_image="$ESP_DIR/initramfs-linux$suffix.img"
/etc/mkinitcpio.d/linux-zen.preset
suffix='-zen' source /etc/mkinitcpio.d/linux.preset
mkinitcpio のポストフックを使う
mkinitcpio のポストフックを使うことで、initramfs の生成後にカーネルと initramfs のイメージを所望のディレクトリに自動でコピーさせることができます。
以下のファイルを作成し、そのファイルに実行可能属性を付与してください:
/etc/initcpio/post/copy-kernel-and-initramfs
#!/usr/bin/env bash kernel="$1" initrd="$2" target_dir="esp/EFI/arch" files_to_copy=() for file in "$kernel" "$initrd"; do if [[ -n "$file" ]] && ! cmp -s -- "$file" "${target_dir}/${file##*/}"; then files_to_copy+=("$file") fi done (( ! ${#files_to_copy[@]} )) && exit 0 cp -af -- "${files_to_copy[@]}" "${target_dir}/"
pacman フックを使う
最後の選択肢は、トランザクションの最後に実行する pacman フック です。
最初のファイルは、関連するファイルを監視するフックで、ファイルが前のトランザクションで変更された場合に実行されます。
/etc/pacman.d/hooks/999-kernel-efi-copy.hook
[Trigger] Type = Path Operation = Install Operation = Upgrade Target = usr/lib/modules/*/vmlinuz Target = usr/lib/initcpio/* Target = boot/*-ucode.img [Action] Description = Copying linux and initramfs to EFI directory... When = PostTransaction Exec = /usr/local/bin/kernel-efi-copy.sh
2つ目のファイルはスクリプト自体です。ファイルを作成し、実行可能属性を付与してください:
/usr/local/bin/kernel-efi-copy.sh
#!/bin/sh # # Copy kernel and initramfs images to EFI directory # ESP_DIR="esp/EFI/arch" for file in /boot/vmlinuz* do cp -af "$file" "$ESP_DIR/$(basename "$file").efi" [ $? -ne 0 ] && exit 1 done for file in /boot/initramfs* do cp -af "$file" "$ESP_DIR/" [ $? -ne 0 ] && exit 1 done [ -e /boot/intel-ucode.img ] && cp -af /boot/intel-ucode.img "$ESP_DIR/" [ -e /boot/amd-ucode.img ] && cp -af /boot/amd-ucode.img "$ESP_DIR/" exit 0
ヒントとテクニック
ESP をより大きなパーティションに取り替える
既存のオペレーティングシステムが載っているディスクでは、EFI システムパーティションが #パーティションの作成 章で推奨されているサイズよりも小さいことがあります。例えば、Windows Setup は 4Kn でないドライブ上にはたった 100 MiB の EFI システムパーティションしか作成しません。
そのような場合では、ESP のスペースを使い切らないようにより大きな新しい EFI システムパーティションを作成したほうが良いかもしれません。
Windows から新しいパーティション用に領域を空ける
Windows からは、グラフィカルな「ディスクの管理」(diskmgmr.msc
) やコマンドラインインターフェイスの diskpart.exe
ユーティリティでパーティションを管理できます。
diskmgmr.msc
を管理者として実行してください。
- "(C:)" パーティション (Windows によってデフォルトで作成されるパーティションのうち、これが唯一オンライン状態でリサイズ可能です) を右クリックし、ボリュームの縮小... を選択してください。
- 縮小する領域のサイズとして
4096
を入力し、縮小 をクリックしてください。
これで、"(C:)" パーティションの後ろに 4 GiB の未割り当てのスペースが空くはずです。
Arch Linux か Arch Linux のインストールメディアを起動し、新しいパーティションの作成作業に移ります。
古い ESP を削除し、新規に作成する
まず、EFI システムパーティション内のコンテンツをバックアップしておいてください。例えば、esp が ESP のマウントポイントである場合:
# cp -a esp /esp_backup
EFI システムパーティションをアンマウントしてください:
# umount esp
blkid を実行し、ESP の UUID と PARTUUID の値をメモしてください。これらは後に新しい ESP で再利用します。
# blkid
/dev/sdxY: UUID="XXXX-XXXX" BLOCK_SIZE="512" TYPE="vfat" PARTLABEL="EFI system partition" PARTUUID="YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY"
gptfdisk パッケージの sgdisk を使って古い ESP を削除してください:
# sgdisk --delete=Y /dev/sdx
最大の未割り当てスペースに新しいパーティションを作成します。ここで先の古い PARTUUID と PARTLABEL を利用します:
# sgdisk --align-end --largest-new=0 --typecode=0:ef00 --change-name=0:'EFI system partition' --partition-guid=0:YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY /dev/sdx
fdisk でパーティションの一覧を表示し、新しい 4 GiB の EFI システムパーティションが作成されたことを確認してください:
# fdisk -l /dev/sdx
... Device Start End Sectors Size Type /dev/sdx1 158099456 166488063 8388608 4G EFI System /dev/sdx2 206848 239615 32768 16M Microsoft reserved /dev/sdx3 239616 158099455 157859840 75.3G Microsoft basic data /dev/sdx4 166488064 167768063 1280000 625M Windows recovery environment Partition table entries are not in disk order.
パーティション番号はパーティションの削除と作成の際にソートされません。なので、EFI システムパーティションの番号は以前と同じである可能性が高いです。
パーティションを FAT32 でフォーマットし、先ほどメモした古い UUID をここで再利用します (ただし、UUID からはダッシュ記号を抜いてください):
# mkfs.fat -F 32 -i XXXXXXXX /dev/sdxY
最後に、新しいパーティションをマウントし、バックアップしたコンテンツを保存してください:
# mount /dev/sdxY esp # cp -a /esp_backup/. esp/
esp.automount
を停止していた場合は、再び開始してください。
隣接するスワップパーティションを犠牲にして ESP を大きくする
EFI システムパーティションのすぐ後ろにスワップパーティションが存在する場合、それを犠牲にして EFI システムパーティションを大きくすることができます。例えば、以下と似たようなパーティションレイアウトの場合です:
# fdisk -l /dev/sdx
... Device Start End Sectors Size Type /dev/sdx1 2048 616447 614400 300M EFI System /dev/sdx2 616448 9005055 8388608 4G Linux swap /dev/sdx3 9005056 125827071 116822016 55.7G Linux root (x86-64)
まず、スワップパーティションを無効化し、fstab から削除してください。
fdisk を使ってスワップパーティションを削除し、EFI システムパーティションを拡大してください:
- 次を実行してください:
# fdisk -l /dev/sdx
d
コマンドを使ってスワップパーティション (上記のレイアウト例ではパーティション番号2
です) を削除してください。e
コマンドを使って EFI システムパーティション (上記の例ではパーティション番号1
です) を拡大してください。提案された新しいサイズをそのまま使い、Enter
を押してください。w
コマンドで変更をディスクに書き込んで、fdisk を終了してください。
パーティションをリサイズしたら、パーティション内のファイルシステムもリサイズする必要があります。fatresize(1) は動作しないうえ、libparted は 特定のサイズの FAT ボリュームをリサイズできないため、唯一の手段は既存の ESP ファイルシステムからファイルをバックアップしておいて、より大きな新しくファイルシステムを作成することです。
新しいファイルシステムで再利用するために ESP の UUID をメモしてください:
$ lsblk -dno UUID /dev/sdxY
XXXX-XXXX
EFI システムパーティションのコンテンツをバックアップしてください。例えば、esp が ESP のマウントポイントである場合:
# cp -a esp /esp_backup
EFI システムパーティションをアンマウントしてください:
# umount esp
古いファイルシステムから残留物を残さないようにするために、ESP からファイルシステムのシグネチャを削除してください:
# wipefs -af /dev/sdxY
パーティションを FAT32 でフォーマットし、先ほどメモした古い UUID をここで再利用します (ただし、UUID からはダッシュ記号を抜いてください):
# mkfs.fat -F 32 -i XXXXXXXX /dev/sdxY
最後に、新しいパーティションをマウントし、バックアップしたコンテンツを保存してください:
# mount /dev/sdxY esp # cp -a /esp_backup/. esp/
esp.automount
を停止していた場合は、再び開始してください。
スワップパーティションは無くなってしまったので、スワップファイルでスワップをセットアップしてください。
トラブルシューティング
ソフトウェア RAID1 上に ESP を配置する
ESP を RAID1 アレイに置くことも可能ですが、データが破損する危険性があり、また、ESP を作成する際に様々な注意をする必要があります。詳細は [7] と [8] を、解決策付きの詳細なガイドは UEFI booting and RAID1 を見てください。
鍵となる部分は、RAID メタデータをパーティションの最後に保持するために --metadata 1.0
を使うことです。さもないと、ファームウェアがアクセスできなくなります:
# mdadm --create --verbose --level=1 --metadata=1.0 --raid-devices=2 /dev/md/ESP /dev/sdaX /dev/sdbY
ファームウェアから EFI ディレクトリが見えない
FAT ファイルシステムにボリューム名(例: ファイルシステムラベル)をつける場合、EFI
以外の名前にしてください。(ボリューム名が EFI のディレクトリ名と一致するので)一部のファームウェアでバグを引き起こす可能性があります。その結果、ファームウェアは EFI ディレクトリが存在しないかのように振る舞います。