QEMU/実機共に起動できるDebianをUSBフラッシュメモリに構築する

本記事は少し早いですがDebian/Ubuntu Advent Calendar 2017の12/12(火)向けに書いた記事です。Debian関係で最近やったことを記事にしてみます。


Linuxカーネルのブロックレイヤー向けドライバを動かしてみる時などに、Linuxカーネルごと別の環境が欲しくなります。複数台PCを持っていなかったりすると、仮想マシンとして立ち上げることを考えますが、実行速度を求めたい時など、仮想環境を直接PC上で実行したい時もあります。


本記事ではQEMU上でも実機上でも起動できるDebian環境をUSBフラッシュメモリへ構築する方法を紹介します。


といっても、結論から書くと単にQEMUを使用してUSBフラッシュメモリへインストールするだけです。ただし、UEFI向けにインストールする場合、少し変更が必要な箇所があります。


この記事ではQEMUを使用してUSBフラッシュメモリDebian環境を構築する方法を紹介します。当然、Debianインストールディスクを直接実機で起動してインストールを行った方がインストールにかかる時間は短くて済むのですが、インストールしている最中に同じPCで別の作業を行えるのは便利です。

レガシーBIOS向け

$ sudo qemu-system-x86_64 -m 1024 -cdrom debian-9.2.1-amd64-netinst.iso -hda /dev/sdb

USBフラッシュメモリは /dev/sdb で認識されているとします
※ インストールディスクは"debian-9.2.1-amd64-netinst.iso"というファイル名でダウンロードしてあるとします。
QEMUへ割り当てるメモリは1GBとしていますが(-mオプション)、搭載されているメモリに合わせて適宜変更してください


インストール完了後、実機で起動する際はBIOS設定を変更し、インストールしたUSBフラッシュメモリから起動してください。


また、QEMU上で起動する際は以下のコマンドを実行します。

$ sudo qemu-system-x86_64 -m 1024 -hda /dev/sdb

UEFI向け

QEMUにはUEFI対応のファームウェアは含まれていないため、OVMF(Open Virtual Machine Firmware)パッケージをインストールします。

$ sudo apt install ovmf


その後、以下のコマンドでUSBフラッシュメモリへインストールを行います。

$ sudo qemu-system-x86_64 -bios OVMF.fd -m 1024 -cdrom debian-9.2.1-amd64-netinst.iso -hda /dev/sdb

※ レガシーBIOS向けのコマンドラインへ"-bios OVMF.fd"オプションを追加しただけです


インストール完了後、QEMUからはそのまま以下のコマンドで起動できます。

$ sudo qemu-system-x86_64 -bios OVMF.fd -m 1024 -hda /dev/sdb


しかし、実機では起動できないと思われます。(少なくとも私のPC(Lenovo Thinkpad)では起動不可)


レガシーBIOSの場合、PC起動時にBIOSは起動ディスクの先頭512バイト(MBR)を見に行きます。対してBIOSUEFI準拠の場合、UEFIはFATファイルシステムを認識できるのでPC起動時に起動ディスクの第1パーティションに決まったファイル名でOS起動用のファイル(主にブートローダー)が置かれているかを見に行きます。


DebianUEFI向けにインストールした時、第1パーティションには"efi/debian/grubx64.efi"というパスでブートローダー(GRUB)がインストールされますが、UEFIファームウェアによってはこのパスでこのファイルを見つけられなかったりします。UEFIの仕様としては"EFI/BOOT/BOOTx64.EFI"(FATなので大文字小文字区別無し)というパスを探しに行きます[*1]。
[*1] http://www.uefi.org/specifications


そのため、DebianをインストールしたUSBフラッシュメモリ第1パーティションの"efi/debian/grubx64.efi"を"efi/boot/bootx64.efi"へコピーしておけば、実機から起動できるようになります。

$ sudo mount /dev/sdb1 /mnt
$ sudo mkdir -p /mnt/efi/boot
$ sudo cp /mnt/efi/debian/grubx64.efi /mnt/efi/boot/bootx64.efi
$ sudo umount /mnt