はじめに
BitVisor を UEFI 環境にインストールする機会があったので、その手順をまとめます。 内容は EFI のブートエントリーの設定をしているだけで真新しいことは特にないですが、いつかまた自分が同じことをする時のために書き残そうと思います。
目標
UEFI 環境で以下のように BitVisor の起動ができるようにする。
- OS の再起動前に何かしらの操作(コマンドを実行)をした場合にだけ、再起動後に BitVisor が起動する。
- 何も指定せずに再起動した際には、BitVisor なしで OS が起動する。
このようにしたいのは、壊れた BitVisor のバイナリをインストールしてしまった時でもマシンを再起動すれば復帰できるようにしたいためです。リモートマシンで BitVisor の開発をする際に、このようになっていると非常に便利です。
対象環境
- CentOS 8
- UEFI ブート
-
/boot/efi
以下に EFI パーティションをマウント
問題
UEFI + Grub 環境で BitVisor を起動する方法や BIOS + Grub 環境で上記条件を満たす設定の方法については、既に解説記事があります。
- BitVisorをUbuntu 18.04.1でビルドしてUEFIブートする(GRUB2) by @morimolymoly: https://qiita.com/morimolymoly/items/a571942880d8ba55f037
- BitVisor を Grub 経由で起動するときの便利設定 by @deep_tkkn: https://qiita.com/deep_tkkn/items/30b44f89321d414d6a30
しかし、これらを組み合わせようとしても上記の目標はうまく達せられませんでした…
(詳細はあまり調べていませんが、おそらく UEFI 環境の GRUB で chainload loadvmm.efi
とすると、その後 GRUB に戻って来ずに別の UEFI エントリーを起動しようとしてしまうためにうまくいかないのだと思います。)
そこで、今回は Grub ではなく EFI の boot entry を設定することで解決したいと思います。
設定方法
BitVisor の準備
まずは BitVisor をダウンロードして、 bitvisor.elf
と loadvmm.efi
をビルドします。 これらの方法は、先出の解説記事 に詳しく解説されていますので,ここではコマンドリストだけ載せます。
yum install mercurial gcc make mingw64-gcc #mingw64-gcc は loadvmm.efi のビルドに必要
hg clone http://hg.code.sf.net/p/bitvisor/code bitvisor
cd bitvisor
make config # 適当にオプションを指定
make -j3 #並列数はコアの数などに合わせてお好みでどうぞ
make -C boot/uefi-loader
popd
sudo cp bitvisor.elf boot/uefi-loader/loadvmm.efi /boot/efi/EFI/BOOT/
EFI ブートエントリーの設定
基本的には efibootmgr
を使ってブートエントリーの設定をするだけで設定できます。 手順は以下の3つ
- ブートエントリーの追加
- エントリーの優先順位の設定
- (BitVisor の起動前) 次回起動するエントリーの指定
コマンドとしては以下の3つだけです。
efibootmgr --create --disk /dev/sdX --part 1 --loader \\EFI\\BOOT\\loadvmm.efi --label BitVisor #エントリー追加
efibootmgr -o 0003,0004,0000,0005,0001,0002 #OS のエントリーが優先されるように変更
efibootmgr -n $(efibootmgr | grep BitVisor | cut -c 5-8) #BitVisor を起動したい時のみ実行
詳しくは以下で説明します。
ブートエントリーの追加
まずは efibootmgr
で現在のブートエントリーの状態を確認しておきます。
# efibootmgr
BootCurrent: 0003
Timeout: 1 seconds
BootOrder: 0003,0000,0005,0001,0002
Boot0000* CentOS Linux
Boot0001* Hard Drive
Boot0002* USB
Boot0003* CentOS Linux
Boot0005* UEFI OS
#
この BootOrder: 0003,0000,0005,0001,0002
というところをメモしておくと、あとで起動順序を設定するときに迷わなくて済むと思います。 次にブートエントリーを追加します。以下のコマンドでエントリーを追加できます。
efibootmgr --create --disk /dev/sdX --part 1 --loader \\EFI\\BOOT\\loadvmm.efi --label BitVisor
オプションの意味は以下の通りです。
-
--disk /dev/sdX
: EFI パーティションのあるブロックデバイスを指定。UUID で指定しなくてもefibootmgr
側でよしなにやってくれます。 -
--part 1
: パーティション番号を指定。例えば/dev/sda2
に EFI パーティションがある場合は2
を指定してください。 -
--loader \\EFI\\BOOT\\loadvmm.efi
: ブートローダーの EFI ファイルのパスを指定。パーティション内のルートからのパスを Windows 風 (\
区切り)で指定します。エスケープのために区切り文字が\\
になる点に注意してください。 -
--label BitVisor
: ブートエントリーにつけるラベル (名前) を指定。お好みで分かり易い名前をつけましょう。
エントリーの優先順位の変更
エントリーの追加後、再度ブートエントリーの状態を確認します。
# efibootmgr
BootCurrent: 0003
Timeout: 1 seconds
BootOrder: 0004,0003,0005,0001,0002
Boot0001* Hard Drive
Boot0002* USB
Boot0003* CentOS Linux
Boot0004* BitVisor
Boot0005* UEFI OS
ここでは、0004 に BitVisor のエントリーが追加されています。 また、BootOrder は 0004 が最優先になっているため、このまま再起動すると BitVisor が常に起動指定します。 これは避けたいので、以下のコマンドで起動順序の設定を行います。
efibootmgr -o 0003,0004,0000,0005,0001,0002
見ての通り efibootmgr -o
の後にカンマ区切りでブートエントリーの番号を指定すれば OK です。 今回は元々最優先だったエントリー 0003 を最初に持ってきて、それ以外は変更なしという風にしました。 これで、普通に再起動すれば BitVisor ではなく CentOS が起動するようになります。
次回起動時に選択するエントリーの指定
efibootmgr で次回起動時に選択する EFI ブートエントリーを一時的に変更することができます。 再起動前に以下のコマンドで BitVisor のエントリーを一時的に選択するようにすれば、BitVisor の起動もできます。
efibootmgr -n $(efibootmgr | grep BitVisor | cut -c 5-8)
# reboot で再起動後 BitVisor --> CentOS の順で起動
efibootmgr に関して参考にしたページ
- efibootmgr その2 - UEFIブートマネージャーにブートローダーを登録する: https://kledgeb.blogspot.com/2015/11/efibootmgr-2-uefi.html
- efibootmgr その4 - エントリーの起動順を変更する・重複したエントリーの起動順を削除する・エントリーの起動順を削除する: https://kledgeb.blogspot.com/2015/11/efibootmgr-4.html
- efibootmgr その5 - PCの次回起動時に1度だけ実行するエントリーを設定する・PCの次回起動時に1度だけ実行するエントリーを削除する: https://kledgeb.blogspot.com/2015/11/efibootmgr-5-pc1pc1.html
おわりに
上記設定で、
- BitVisor を起動したいときには
efibootmgr -n $(efibootmgr | grep BitVisor | cut -c 5-8)
実行後に再起動 - BitVisor なしで再起動したいときにはなにもせずに再起動
という風に使えます。 ssh 越しでも BitVisor を起動したりしなかったりの制御ができるため便利かと思います。