EFIマルチブート(1): SLES12, CentOS7, Fedora21, Ubuntu15.04, SL6.4, Windows8

約2年前にASUSノートPC X202Eを購入(4万円)、EFIのマルチブートでLinuxをインストールしましたが、今回はそれを久々に更新し、最新版のLinuxディストリビューションをインストールしました。

インストールしたOS (すべて64ビット版):

OS リリース日 ISOイメージ
Ubuntu 15.04 2015年 4月 ubuntu-15.04-desktop-amd64.iso
Fedora 21 Workstation 2014年12月 Fedora-Live-Workstation-x86_64-21-5.iso
SUSE Linux Enterprise Server 12 (SLES 12) 2014年10月 (評価版。SUSEのイベントに参加した時に入手)
CentOS 7 2014年 6月 CentOS-7-x86_64-DVD-1503-01.iso
Scientific Linux 6.4 (SL6.4) 2013年 3月 (2年前にインストールしたまま)
Windows 8 2012年10月 (PC購入時のプリインストールOS)

EFIの設定:
ASUSノートPC X202EではAmerican Megatrends社のEFIが使われています。
以下の設定でインストールしました。

・Launch CSM(Compatibility Support Module: BIOS互換モード) → [disabled]
・Secure Boot Control → [disabled]
   設定画面は*こちら*を参考にして下さい。

なお、Scientific Linux 6.4以外はSecure Bootをdisabledでインストールした後でもブートローダの選択によってSecure Bootに対応します。

EFI NVRAMのブートエントリの編集
Linuxのインストール時にEFIのNVRAMのエントリにブートローダが登録されますが、見やすくする為と検証の為にインストール後にLinuxのefibootmgrコマンドにより以下のように変更と追加をしました。

インストール時にはエントリ名は次のように設定されていました。
ubuntu15.04→ubuntu、Fedora21→Fedora、SLES12→(sles12, sles12-secureboot)、CentOS7→CentOS、Windows8→Windows Boot Manager

ブートエントリを編集後のエントリ番号、エントリ名、ローダのパス名
(エントリ名でソートしているので、エントリ番号の順にはなっていません)
# efibootmgr -v |sed 's/HD//'|expand|awk -F'[()]' '{printf "%-35s %-35s\n",$1,$4}' |sort -k2
Timeout: 0 seconds                                                     
BootCurrent: 0001                                                      
BootOrder: 0001,000B,0007,0008,0003,0009,0005,0000,0004,0002,0006
Boot0009* EFI-Shell                 \Shellx64.efi                      
Boot0000* Windows Boot Manager      \EFI\Microsoft\Boot\bootmgfw.efi   
Boot0003* centos7-grubx64           \EFI\centos\grubx64.efi            
Boot0004* centos7-shim              \EFI\centos\shim.efi               
Boot0007* fedora21-grubx64          \EFI\fedora\grubx64.efi            
Boot0008* fedora21-shim             \EFI\fedora\shim.efi               
Boot0002* sl6.4-grub                \EFI\redhat\grub.efi               
Boot0005* sles12-grubx64            \EFI\sles12\grubx64.efi            
Boot000B* sles12-shim               \EFI\sles12\shim.efi                    
Boot0001* ubuntu15.04-grubx64       \EFI\Ubuntu\grubx64.efi            
Boot0006* ubuntu15.04-shimx64       \EFI\ubuntu\shimx64.efi 

efibootmgrコマンドの使い方:
主なオプション
-c エントリの作成、-p パーティション番号、-l ローダの名前(パス)、-L エントリラベル(←適当な名前を付ける)
-b パーティション番号(エントリの変更)、-B エントリの削除
 備考1) -bでのエントリの変更はなぜかできない。追加してから削除、あるいは削除してから追加で変更をする。
 備考2) -Bでのエントリの削除はなぜかできない場合がある

[ エントリの一覧表示 ]
 # efibootmgr
[ エントリの詳細情報を一覧表示 ]
 # efibootmgr -v
[ エントリの追加 ]
例) 
 # efibootmgr -c -p 1 -l '\EFI\centos\shim.efi' -L CentOS7-shim
[ エントリの削除 ]
例) 
 # efibootmgr -b 3 -B

ブートローダのパス
EFIの場合、各OSのブートローダはEFI System Partition(ESP)に置きます。特別の理由がない限り、同じ1つのパーティションに置けば良いと思います。今回の場合は/dev/sda1です。
このパーティションのマウントポイントはデフォルトでは/boot/efiとなります。マルチブートでインストールする場合、このパーティションをフォーマットしないように注意が必要です。
デフォルトではこのパーティションのEFIディレクトリの下に各OSごとのサブディレクトリが作成されてその下にブートローダが置かれます。

# df -T /boot/efi
Filesystem     Type 1K-blocks   Used Available Use% Mounted on
/dev/sda1      vfat    303104 124680    178424  42% /boot/efi
# tree -L 1 /boot/efi/EFI
/boot/efi/EFI
├── ASUS
├── Boot
├── Microsoft
├── centos
├── fedora
├── redhat     ← (SL 6.4のローダはこの下に)
├── sles12
└── ubuntu

インストール時はSUSE以外はOSのバージョン番号なしのディレクトリとなるので、古いバージョンのローダが残っている場合は上書きされてわかりにくくなります。インストール前に古いディレクトリは削除するかリネームしておく方が良いかも知れません。
インストール後にディレクトリの名前にバージョン番号を付けるなどして変更も可能だと思いますが、現在はインストール時のディレクトリ名のままにしてあります。

ブートローダとSecure Bootへの対応

エントリ名 ローダのファイル名 SecureBootへの対応
Windows Boot Manager bootmgfw.efi
centos7-shim, fedora21-shim, sles12-shim shim.efi
ubuntu15.04-shimx64 shimx64.efi
ubuntu15.04-grubx64 grubx64.efi
centos7-grubx64, fedora21-grubx64, sles12-grubx64 grubx64.efi ×
sl6.4-grub grub.efi ×

* EFIでSecure Boot をenableに設定し、Secure Boot非対応のブートローダ(署名のない、上記の表でxのもの)を起動しようとすると以下のエラーメッセージが表示されて起動できません。

Secure Boot Violation


Invalid signature detected. Check Secure
Boot Policy in Setup

* shim.efiの場合はEFIのSecure Bootの設定がenableでもdisabledでも起動できます。
* ubuntu15.04の場合は他のディストリビューションと異なり、grubx64.efiはSecure Bootに対応しています。

# dpkg -S /usr/lib/grub/x86_64-efi-signed/grubx64.efi.signed
grub-efi-amd64-signed: /usr/lib/grub/x86_64-efi-signed/grubx64.efi.signed
# dpkg -s grub-efi-amd64-signed
..........
Description: GRand Unified Bootloader, version 2 (EFI-AMD64 version, signed)
...........
This package contains a version of GRUB built for use with the EFI-AMD64
architecture, signed with Canonical's UEFI signing key.

grub.cfgのマルチブートの記述
EFIの設定画面で立ち上げるOSを選択出来ますが手順が面倒です。どれか1つのLinuxのgrub.cfgでマルチブートの設定をした方が便利です。
たまたまUbuntuを最初に更新(インストール)したのでUbuntuのgrub.cfgに他のOSのエントリを登録しましたが、GRUB2を採用しているSLES12, CentOS7, Fedora21でも同じにできるはずです。
EFIからはUbuntuのGRUB2を立ち上げて、そこでOSを選択するようにしました。

Ubuntu15.04では/boot/efi/EFI/ubuntu/grub.cfgから/boot/grub/grub.cfgを呼び出すように設定されているので、/boot/grub/grub.cfgを編集します。
GRUB2の設定ファイルgrub.cfgはLinuxのインストール時に生成されますが、インストール後にgrub-mkconfig(ディストリビューションによってはgrub2-mkconfig)コマンド(シェルスクリプト)を実行することでも生成できます。

# grub-mkconfig > grub.cfg

grub-mkconfigは/etc/grub.dの下のシェルスクリプトを順に実行することでgrub.cfgを生成します。

# ls -F /etc/grub.d/
00_header*        10_linux*      20_memtest86+*  30_uefi-firmware*  41_custom*
05_debian_theme*  20_linux_xen*  30_os-prober*   40_custom*         README

上記のシェルスクリプトのうち、30_os-proberは他のディストリビューションをほぼ自動検知してエントリを登録してくれますが、意図しないかたちで登録されたり、また再インストールした場合はパーティションのUUIDが変わったりして修正するのが面倒です。そこでgrub-mkconfigを実行する前に「# chmod -x /etc/grub.d/30_os-prober」として30_os-proberを外してからgrub.cfgを生成しました。
そして、41_customが生成する設定を利用し、/boot/grub/custom.cfgをエディタで作成して、ここにUbuntu以外のOSのエントリをすべて登録しました。これだとあとでgrub-mkconfigを実行してもcustom.cfgの内容が変更されることはありません。
他のOSのエントリはchainloaderで各OSのブートローダを呼び出す設定にしました。(この方が記述が簡単)
以下、Fedora21とWindows8のエントリの例ですが、他のLinuxディストリビューションでも同じ要領でできます。(menuentryの名前とchainloaderで指定するローダのパスが違うだけ)

blkidコマンドを実行してEFI System PartitionのUUID(「UUID=」の後に表示される値。太字部分)を確認しておきます。
これをエントリのsearchコマンドの引数で指定します。(なお「PARTUUID=」で表示される値はGPTで設定されているパーティションのGUIDです)

# blkid /dev/sda1
/dev/sda1: LABEL="SYSTEM" UUID="1409-5974" TYPE="vfat" PARTLABEL="EFI System Partition" PARTUUID="ed04135b-bd79-4c7c-b3b5-b0f9c2fe6826"

# vi /boot/grub/custom.cfg
menuentry "Fedora 21 (on sda12)" {
  insmod part_gpt
  insmod fat
  insmod search_fs_uuid
  insmod chain
  search --fs-uuid --set=root --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1 1409-5974
  chainloader /EFI/fedora/shim.efi
}
menuentry "Windows 8 (on sda4)" {
  insmod part_gpt
  insmod fat
  insmod search_fs_uuid
  insmod chain
  search --fs-uuid --set=root --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1 1409-5974
  chainloader /EFI/Microsoft/Boot/bootmgfw.efi
}

次回は各ディストリビューションのインストールに関係したことなどを簡単に書きます。