EFI stubなArch Linuxのインストール

QEMU上の仮想マシンEFI stubなArch Linuxをインストールする。 ここでのホストはUbuntu 16.04.4 TLSとする。 なお[1][2][3][4]を参考にした。

OVMFのダウンロードとArch Linuxのインストールディスクのダウンロード

最初にOVMFをダウンロードして解凍する。 OVMFはTianoCoreをベースにした仮想マシン向けのUEFI実装である。

$ wget https://www.kraxel.org/repos/jenkins/edk2/edk2.git-ovmf-x64-0-20180508.84.g7cd8a57599.noarch.rpm
$ rpm2cpio edk2.git-ovmf-x64-0-20180508.84.g7cd8a57599.noarch.rpm | cpio -idmv
$ cp usr/share/edk2.git/ovmf-x64/OVMF_CODE-pure-efi.fd .
$ cp usr/share/edk2.git/ovmf-x64/OVMF_VARS-pure-efi.fd .

Arch Linuxのインストールディスクをダウンロードする。

$ wget http://ftp.jaist.ac.jp/pub/Linux/ArchLinux/iso/2018.05.01/archlinux-2018.05.01-x86_64.iso

インストール先のディスクイメージを作成する。

$ qemu-img create -f raw arch-amd64.img 32G

仮想マシンの起動と設定

インストールディスクから起動する。 これ以降は仮想マシンでの操作となる。

$ qemu-system-x86_64 -enable-kvm -k ja -m 2048 -localtime -drive if=pflash,format=raw,readonly,file=OVMF_CODE-pure-efi.fd -drive if=pflash,format=raw,file=OVMF_VARS-pure-efi.fd -hda arch-amd64.img -net nic,model=e1000 -net user -cdrom archlinux-2018.05.01-x86_64.iso -boot d

キーボードレイアウトを設定。

# loadkeys jp106

gdiskパーティションを作成。 ここでは/dev/sda1を512MBのEFIパーティション、 /dev/sda2を残りのすべての容量としたLinuxパーティションとした。

# gdisk /dev/sda
Command (? for help):o
Command (? for help):n
Permission number: 1
First sector     : 
Last sector      : +512M
Hex code or GUID : ef00
Command (? for help):n
Permission number: 2
First sector     : 
Last sector      :  
Hex code or GUID : 8300

最後に書き込みを行う。

Command (? for help):w

パーティションをフォーマット

# mkfs.vfat -F32 /dev/sda1
# mkfs.ext4 /dev/sda2

それぞれをマウント。

# mount /dev/sda2
# mkdir -p /mnt/boot
# mount /dev/sda1 /mnt/boot

ダウンロードのミラーサイトを設定。

# nano /etc/pacman.d/mirrorlist

システムのインストール。

# pacstrap -i /mnt base base-devel

fstabの生成。

# genfstab -U -p /mnt >> /mnt/etc/fstab

localeの設定。

# locale-gen
# echo LANG=en_US.UTF-8 > /etc/locale.conf
# export LANG=en_US.UTF-8

キーボードマップの設定。

# echo KEYMAP=jp106 > /etc/vconsole.conf

localtimeの設定。

# rm /etc/localtime
# ln -s /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
# hwclock -u -w

ホスト名の設定。

# echo "arch-vm" > /etc/hostname

DHCPクライアントの設定。

# systemctl enable dhcpcd.service

パスワードの設定。

# passwd

GRUB2の代わりにefibootmgrEFI Variableを設定。

# efibootmgr -d /dev/sda -p 1 -c -L "Arch Linux" -l /vmlinuz-linux -u "root=dev/sda2 rw initrd=initramfs-linux.img"
# efibootmgr -v

exitしてhalt。

# exit
# halt

以下で正しく起動することを確認。

$ qemu-system-x86_64 -enable-kvm -k ja -m 2048 -localtime -drive if=pflash,format=raw,readonly,file=OVMF_CODE-pure-efi.fd -drive if=pflash,format=raw,file=OVMF_VARS-pure-efi.fd -hda arch-amd64.img -net nic,model=e1000 -net user

EFI stubなLinux kernelのビルド

先の説明でインストールしたArch LinuxEFI stubとなっている。 ここでは、ホストでLinux kernelをビルドしそれを仮想マシンにインストールしてみる。

Linuxカーネルのビルド

カーネルをダウンロードする。

$ git clone https://kernel.googlesource.com/pub/scm/linux/kernel/git/torvalds/linux.git --branch v4.17 --depth 1

ホストのconfigをコピーして多少の修正を行い、ホスト上でビルドする。 make menuconfigCONFIG_EFI_STUB=yとなっていることを確認する。 makeするときのjob数はホストのCPUのコア数に応じて変更する。

$ cp /boot/config-4.15.0-33-generic .config
$ make menuconfig
$ make -j9

Linux kernelの仮想マシンへのインストール

仮想マシンのディスクイメージをマウントする。

# /sbin/kpartx -av arch-amd64.img
# mount /dev/mapper/loop0p2 /mnt

ホストでビルドしたカーネル仮想マシンにインストールする。

# make INSTALL_MOD_PATH=/mnt modules_install
# mkdir -p /mnt/var/tmp
# cp System.map /mnt/var/tmp
# cp arch/x86_64/boot/bzImage /mnt/var/tmp
# umount /mnt

最後に仮想マシン上でホストでビルドしたbzImageとSystem.mapをコピーし、 initramfsを生成する。

# cp -f /var/tmp/bzImage /boot/vmlinuz-linux
# cp -f /var/tmp/System.map /boot/System.map
# mkinitcpio -c /etc/mkinitcpio.conf -g /boot/initramfs-linux.img

最後に再起動し、ビルドしたバージョンのカーネルであることを確認する。

参考文献