Ubuntu Weekly Recipe

第441回 QEMU/KVMでUEFIファームウェアを使う

この記事を読むのに必要な時間:およそ 5 分

UEFI(Unified Extensible Firmware Interface)はOSとファームウェアの間の橋渡しを行うインターフェースの仕様です。今回はQEMU/KVMで,このUEFIをサポートしたファームウェアを使用する方法を紹介します。

UEFIとQEMU/KVMとOVMF

いわゆる「PC/AT互換機」とも呼ばれるIntel系CPUを搭載したPCでは,電源投入後からハードウェアの初期化,ブートローダーの起動などを「BIOS」と呼ばれるファームウェアが担っていました※1)。UEFIはこのBIOSを置き換えるための仕様で,機能の強化や起動の高速化,業界団体による標準化などが行われています。ここ数年のx86マシンであればほぼすべてUEFIファームウェアに置き換わっていますし,ARMプラットフォームでもよく使われるU-Bootが最近UEFIをサポートするようになりました。本連載の読者の皆様も,一度ぐらいはUEFIファームウェアに触れていることでしょう。

※1
BIOS(Basic Input/Output System)は,ハードウェアの入出力を担当するファームウェアの総称で,特定の仕様・規格や製品を指す用語ではありません。よってメーカーによってはUEFIファームウェアのことを「UEFIの仕様に対応したBIOSファームウェア」ということで「UEFI BIOS」と呼んだりもします。本記事では「BIOS」は原則として「UEFIには対応していない古いBIOS(レガシーBIOS)」の意味で使うことにします。

Ubuntuも11.10ぐらいからUEFIによる起動をサポートするようになりました。しかしながら初期の頃は,インストーラーがUEFIシステムパーティションを壊してしまうなど,いろいろと問題もあったのです。現在サポートしているリリースであれば,基本的には問題なくUEFIシステム上にUbuntuをインストールできるようになっています。ただし,UEFIファームウェアの実装の違いやデバイス・他のOSとの相性の違いによって,Ubuntuをうまくインストールできない,インストールできたとしてもいくつかのデバイスが動かない,といった場合があることも事実です※2)。UEFIに限ったことではありませんが,Ubuntuをインストールする場合はあらかじめシステム上のデータのバックアップをとり,何かあったら復元できるようにしておきましょう。

※2
たとえば,Windowsの「高速スタートアップ」機能を切る,UEFI上の「Fast Boot」「セキュアブート」設定を無効化する,UEFI上の「CSM」「Legacy BIOS」を有効化するなどの方法を使えば回避できる場合もあります。ただし,設定の変更によって今度は他のOSが起動しなくなるリスクもあります。

さて,普段は他のOSで生活し,Ubuntuは仮想マシン上でのみ使用している方もいることでしょう。その場合はおそらくUEFIではなくBIOSを用いたインストールになるはずです。仮想マシン上でもUEFIの恩恵を受けたい場合は,仮想マシンの設定を明示的に変更する必要があります。たとえばVirtualBoxであれば,2009年にリリースされた3.1の頃からEFIファームウェアを使った起動ができるようです※3)。QEMU/KVMの場合は,その本体にはUEFIファームウェアは含まれていません。その代わり-biosオプションで使用するファームウェアを指定できます。この-biosオプションにFLOSSなUEFIファームウェアの実装であるOVMF(Open Virtual Machine Firmware)を指定すれば,UEFIブートできるというわけです。

※3
とはいえあくまで「expermiental support」であり,ドキュメントから「experimental」が消える様子もないため,どこまできちんと使えるかは実際に試してみないとわかりません。現実問題として,ゲストのDebian/Ubuntuが起動しなくなるという問題もあるようです。

そこで今回は,ホストOSをUbuntu 16.04 LTSとした上でQEMU/KVMを用いる時に,ゲストOSをUEFIファームウェアを用いて起動する方法を紹介します。

OVMFのインストールと基本的な使い方

QEMU/KVM標準のBIOSファームウェアはSeaBIOSです。seabiosパッケージから提供されていますし,QEMUをインストールすれば自動的にこのパッケージがインストールされます。

$ sudo apt install qemu-kvm
$ apt policy seabios
seabios:
  インストールされているバージョン: 1.8.2-1ubuntu1
  候補:               1.8.2-1ubuntu1
  バージョンテーブル:
 *** 1.8.2-1ubuntu1 500
        500 http://jp.archive.ubuntu.com/ubuntu xenial/main amd64 Packages
        500 http://jp.archive.ubuntu.com/ubuntu xenial/main i386 Packages
        100 /var/lib/dpkg/status

普通にQEMU/KVMから仮想マシンを起動しただけだとSeaBIOSが非対話モードで起動しますが,-boot menu=onオプションを付けて起動すると,F12キーでBISOメニュー画面が表示されます※4)。

※4
SeaBIOS 1.9.0からはF12キーではなく,ESCキーになるようです。
$ qemu-system-x86_64 -boot menu=on

図1 メニューと言ってもブートデバイスの選択のみ

画像

メニューはシンプルですがSeaBIOSそのものの設定項目は多彩で,ブートスプラッシュ画像などはQEMUの-bootオプション経由でも指定できます

従来のBIOSの話はこれくらいにしておいて,UEFIファームウェアをインストールしましょう。Ubuntuだとovmfパッケージをインストールするだけです。

$ sudo apt install ovmf

OVMFはUEFIファームウェアのFLOSSな実装です。UEFIの前身であるEFIを開発していたIntelが,EFI仕様の「好ましい実装」としてTianoCoreを開発していました。EFIがUEFIになるにあたってEFIアプリケーションの開発環境を整理したものが現在のEDK IIであり,EDK IIによるサンプルアプリケーションのひとつがOVMFです。どちらもBSDライセンスで提供されています※5)。よってEDK IIの最新のソースコードをダウンロードしてきて,自前のOVMFファイルを作成することも可能です。

※5
ファイルによって二条項だったり三条項だったり四条項だったりします。また,FATまわりでDFSGに準拠していないライセンスのコードが存在するため,コンポーネントはmultiverseになっています。このライセンス問題は,最新のEDK IIでは修正されているようです。

QEMU/KVMでOVMFを指定する方法はいくつか存在します。一番手っ取り早いのは-biosオプションにファームウェアのファイル名を渡す方法です。

$ qemu-system-x86_64 -bios OVMF.fd

図2 起動時にロゴが表示される

画像

図3 ESCキーでUEFIメニュー

画像

ブート順やブートデバイスの指定だけでなく,言語の変更やネットワーク設定,セキュアブートの設定など,UEFIらしくさまざまな機能に対応しています。ただし-biosオプションでファームウェアを指定するだけだと,設定は保存されません。一度QEMUプロセスを終了すると,リセットされてしまいます。もしUEFIファームウェアの設定画面の内容を保存したかったら,-pflashオプションでファームウェアを指定する必要があります。この場合,設定内容は指定したファイルの変数領域0x00000から0x20000まで)に書き込まれることになります。よって,あらかじめファイルをコピーしておきましょう。

$ cp /usr/share/ovmf/OVMF.fd .
$ qemu-system-x86_64 -pflash ./OVMF.fd

この状態でUEFIの設定インターフェースを開き,何がしかの設定を行った上で保存してQEMUを終了してください。OVMF.fdのバイナリダンプを確認するとオリジナルのそれと変わっていることがわかるかと思います。

OVMF.fdは前半に変数データを保存するNVRAM領域を,後半にファームウェアのコード本体を記録しています。よってOVMF.fd全体をコピーするのではなく,不変なコード領域は共有し,NVRAM領域だけインスタンスごとに保存したいところです。実はovmfパッケージは,コード領域とNVRAM領域がそれぞれ別になったファイルも用意されています。それを使えば,サイズの小さいNVRAM領域だけ流用することも可能です。

$ cp /usr/share/OVMF/OVMF_VARS.fd sample.fd
$ qemu-system-x86_64 \
    -drive if=pflash,format=raw,readonly,file=/usr/share/OVMF/OVMF_CODE.fd \
    -drive if=pflash,format=raw,file=sample.fd

後述するvirt-managerなどは,このようなオプションを自動的に付加する作りになっています。

ちなみに,UEFIには「UEFI Shell」と呼ばれるシェル環境が用意されています。設定メニューの「Boot Manager」から「EFI Internal Shell」を選択すれば,EFI Shellが立ち上がるはずです。このシェルは,おもにUEFIアプリケーションのデバッグに使われるものですが,ブートローダーが起動する前のハードウェアの状態や設定の確認,スクリプトの実行なども行えます。help -bで使用できるコマンド一覧が表示されますので,一度遊んでみるといいでしょう。なお-bオプションは,実行結果が画面上を流れすぎてしまうことを抑止するオプションです。UEFI Shell上のたいていのコマンドで使用できます。

図4 OVMFのEFI Shell環境

画像

著者プロフィール

柴田充也(しばたみつや)

Ubuntu Japanese Team Member株式会社 創夢所属。数年前にLaunchpad上でStellariumの翻訳をしたことがきっかけで,Ubuntuの翻訳にも関わるようになりました。

コメント

コメントの記入