QEMU上でWindows10の仮想PCを動かしていたが、そろそろWindows11に対応冴えておく必要があると思い、アップグレードしようとした。
結論的には、Win10はBIOSで動いていたのに対し、Win11はUEFIセキュアブートにしなければならなく、HDDイメージにEFIパーティションなかったので新規インストールをした。
Win10のときと同様、SpiceのRemote viewerに音が流れてこない問題は残っているが、一応完了したのでメモ。
Windows11のISOイメージを用意する。
兎にも角にも、Windows11のISOイメージは必要。
https://www.microsoft.com/ja-jp/software-download/windows11
UEFIファームウェアを用意する。
UEFIのファームウェアイメージが必要になるので、EDK IIのOVMFを導入する。が、すでにインストールされていた(sys-firmware/edk2-ovmf)。
OVMFのイメージの中に、UEFIの設定情報まで書き込まれてしまうため、仮想VM1台毎に1つのイメージを作ることになる。ただ、1台毎にOVMFのイメージ全体を用意するのはディスクがもったいないので、設定情報を保存する部分だけを切り出したイメージと併用する。
# cp -a /usr/share/edk2-ovmf/OVMF_VARS.fd /data/VM_images/OVMF_VARS_win11.fd
セキュアブートができるイメージ OVMF_CODE.secboot.fd を利用するのだが、SMMサポートありになっているため、-machineオプションにsmm=onを足す必要がある。また、S3サポートが有効になっていると起動してこないため、-globalオプションの中でICH9-LPC.disable_s3=1を入れてS3を無効化する必要がある。
このあたりが参考情報。
- https://en.opensuse.org/Software_TPM_Emulator_For_QEMU
- https://wiki.archlinux.org/title/QEMU#VM_does_not_boot_when_using_a_Secure_Boot_enabled_OVMF
- https://github.com/tianocore/edk2/blob/master/OvmfPkg/README
仮想TPMを用意する。
仮想TPMの導入のため、app-crypt/swtpmを導入する。
# emerge -uDNtpv swtpm
QEMUで仮想VMを呼び出す前に、swtpmで作った仮想TPMを起動させる必要がある。サービス化しようとも考えたが、仮想VM起動時に仮想VMが仮想TPMを掴んだ後、その仮想VMを終了させると仮想TPMのプロセスも無くなってしまうような挙動をしているので、仮想VM起動スクリプトに埋め込んだ。
virt-managerを使っていれば、swtpmを起動時に自動的に呼び出してくれる設定もあるらしいが、うちではqemuを直接呼び出しているので、対象外。
今回は、ソケットを使って仮想TPMをゲストOSに引き渡すことにした。
# mkdir /data/VM_images/tpm0 # swtpm socket --tpm2 --tpmstate dir=/data/VM_images/tpm0 --ctrl type=unixio,path=/data/VM_images/tpm0/swtpm-sock --log level=20
最後の--log level=20は最終的には削除して、画面上にログが出てくるのを抑止した。
virtioのためのドライバを用意する。
virtioのドライバは、Windows11のインストール時の標準ドライバとして用意されていないため、virtio-win.isoを用意しておく
https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/から最新バージョンをダウンロード
OSを入れるための仮想ディスクを用意する。
シンプロビジョニングされるのと、Win11の要件を満たすため64Gのサイズに。(Win11の要件:https://www.microsoft.com/ja-jp/windows/windows-11-specifications)
# qemu-img create -f qcow2 Win11VM_master.img 64G Formatting 'Win11VM_master.img', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=68719476736 lazy_refcounts=off refcount_bits=16
QEMU起動のためのスクリプトを用意
今までWin10用に使っていたものを再利用して、Win11で必要なTPM 2.0やUEFIセキュアブートの設定を追加。
ちなみに、ここではサウンドカードにAC97を指定しているが、Win10で使えたドライバがWin11では使えなくなっているので、最終的にはintel-hdaに変更した。
下記のスクリプトで、前半の太字しているところがUEFIセキュアブートの設定、後半の太字のところが仮想TPM 2.0の設定。
#!/bin/sh
SPICE_PORT=5924
echo "spice://192.168.1.2:${SPICE_PORT}"
swtpm socket --tpm2 --tpmstate dir=/data/VM_images/tpm0 --ctrl type=unixio,path=/data/VM_images/tpm0/swtpm-sock &
exec qemu-system-x86_64 \
\
-global driver=cfi.pflash01,property=secure,value=on \
-drive if=pflash,format=raw,unit=0,file=/usr/share/edk2-ovmf/OVMF_CODE.secboot.fd,readonly=on \
-drive if=pflash,format=raw,unit=1,file=/data/VM_images/OVMF_VARS_win11.fd \
\
-machine type=q35,smm=on,accel=kvm \
-global ICH9-LPC.disable_s3=1 \
\
-object rng-random,id=rng0,filename=/dev/urandom -device virtio-rng-pci,rng=rng0 \
-enable-kvm \
-cpu host \
-cdrom /data2/Win11_Japanese_x64v1.iso \
-drive file=/data2/virtio-win.iso,media=cdrom \
-drive file=/data/VM_images/Win11VM_master.img,if=virtio,index=0,media=disk,cache=none \
-net nic,macaddr=00:00:00:00:00:02,model=virtio -net tap,ifname=tap0,script=no,downscript=no,vhost=on \
-m 4G \
-name "Windows" \
-rtc base=localtime,clock=host \
-smp 4,sockets=1,cores=4 \
-spice port=${SPICE_PORT},addr=0.0.0.0,disable-ticketing=on,streaming-video=filter,playback-compression=on \
-audiodev spice,id=snd0 \
-device AC97,audiodev=snd0 \
-device virtio-serial-pci \
-device virtserialport,chardev=spicechannel0,name=com.redhat.spice.0 \
-chardev spicevmc,id=spicechannel0,name=vdagent \
\
-chardev socket,id=tpmc,path=/data/VM_images/tpm0/swtpm-sock \
-tpmdev emulator,id=tpm0,chardev=tpmc \
-device tpm-tis,tpmdev=tpm0 \
\
-vnc 0.0.0.0:0 -k ja \
-monitor stdio \
-boot once=d \
"$@"
仮想VMを起動
上記シェルスクリプトを起動すると、Remote Viewerで「Press any key to boot from CD or DVD......」と表示されるので、タイムアウトする前になにかキーを押してDVDからの起動を行う。
あとは通常のWindowsのインストールと同じなので省略するが、途中のインストール先ディスクの指定の際、仮想ディスクが見えていない点に注意が必要。
これは、前述のvirtioのドライバがないため、ディスクを見つけられないことによる。「ドライバーの読み込み(L)」のところからvirtio-win.isoに入っているドライバを取り込む。
isoイメージの直下にamd64とi386とがあるので、利用しているCPUに合わせて選択し、w11もしくはw10のフォルダを選んでやると後はWindowsがうまく処理してくれる。
Windows11のインストールが完了したら、virtio-win.isoの「virtio-win-guest-tools.exe」で必要なドライバを一式導入する。
ちなみに、spice-guest-tools.exeを入れると、Spice VD agentサービスが2個登録されてしまうので、spice-guest-tools.exeは入れなくても良さそう(しかもspice-guest-toolsに入っているvdservice.exeの方が更新日時が古い)。
起動スクリプトの修正
インストールが終わると、Win11のイメージやvirtio-win.isoを読み込む必要がなくなるので、起動スクリプトから削除する。
Win10のときからだが、物理PCを入れ替えてCPUをCore i7からRyzenにしてから、-vga qxlをつけて起動すると、起動時に「qxl_send_events: spice-server bug: guest stopped, ignoring」と警告が出る。
Win10の際は、画面を見るとWindowsの修復モードに入っていたのでqxlは使わないようにしていた。ただ、Win11にしてから起動したら、初回は警告も出ずに修復モードにも入らなかったので、解決されたのかと思っていたら、しばらくしたたら警告も出るし修復モードに入るようになったので、再度qxlを使わないようにした。
その後、いろいろと調べていた際、spice-guest-toolsを削除して起動すると、警告は出るものの修復モードには入らないことを発見したので、qxlを有効にした。
#!/bin/sh
SPICE_PORT=5924
echo "spice://192.168.1.2:${SPICE_PORT}"
swtpm socket --tpm2 --tpmstate dir=/data/VM_images/tpm0 --ctrl type=unixio,path=/data/VM_images/tpm0/swtpm-sock &
exec qemu-system-x86_64 \
\
-global driver=cfi.pflash01,property=secure,value=on \
-drive if=pflash,format=raw,unit=0,file=/usr/share/edk2-ovmf/OVMF_CODE.secboot.fd,readonly=on \
-drive if=pflash,format=raw,unit=1,file=/data/VM_images/OVMF_VARS_win11.fd \
\
-machine type=q35,smm=on,accel=kvm \
-global ICH9-LPC.disable_s3=1 \
\
-device ich9-ahci,id=ahci \
-object rng-random,id=rng0,filename=/dev/urandom -device virtio-rng-pci,rng=rng0 \
-enable-kvm \
-cpu host \
-drive file=/data/VM_images/Win11VM_master.img,if=virtio,index=0,media=disk,cache=none \
-net nic,macaddr=00:00:00:00:00:02,model=virtio -net tap,ifname=tap0,script=no,downscript=no,vhost=on \
-m 4G \
-name "Windows" \
-rtc base=localtime,clock=host \
-smp 4,sockets=1,cores=4 \
-spice port=${SPICE_PORT},addr=0.0.0.0,disable-ticketing=on,streaming-video=filter,playback-compression=on \
\
-audiodev spice,id=snd0 \
-device intel-hda \
-device hda-output,audiodev=snd0 \
\
-device virtio-serial-pci \
-device virtserialport,chardev=spicechannel0,name=com.redhat.spice.0 \
-chardev spicevmc,id=spicechannel0,name=vdagent \
\
-chardev socket,id=tpmc,path=/data/VM_images/tpm0/swtpm-sock \
-tpmdev emulator,id=tpm0,chardev=tpmc \
-device tpm-tis,tpmdev=tpm0 \
\
-vnc 0.0.0.0:0 -k ja \
-monitor stdio \
-vga qxl \
"$@"
ハマったこと
「Guest has not initialized the display (yet).」エラー
Win10のイメージをそのまま利用してUEFIのセキュアブート(OVMF_CODE.secboot.fdを使用)をしようとしたら「Guest has not initialized the display (yet).」とだけ出て、先に進まない。
これは、前述のSMMの有効化設定や、S3の無効化設定が入っていないためで、どちらがかけていても同じエラーになる。
ブート可能デバイスが見つからない
セキュアブートではないUEFIファームウェア(OVMF_CODE.fdを使用)しても、上記のセキュアブート対応のUEFIの問題を解決しても、以下のようなエラーが出て起動イメージを見つけることができない。
「BdsDxe: failed to load Boot0001 "UEFI QEMU DEV-ROM QM00005 " from PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x2,0xFFFF,0x0): Not Found」
「BdsDxe: failed to load Boot0002 "UEFI Misc Device" from PciRoot(0x0)/Pci(0x5,0x0): Not Found」
「Start PXE over IPv4.」
これは、Win10のディスクイメージがBIOSを想定しており、EFIパーティションが作成されていなかったため。
ちなみに、「Boot0001」や「Boot0002」は、ブートの優先順位1位、2位を表していると思われる。
「Press any key to boot from CD or DVD......」と出ているが、UEFIがエラーを出している。
これは、SpiceのRemote Viewerを立ち上げるのが遅く、DVDからの起動待ち時間が過ぎてしまったため、UEFIが違うデバイスから起動させようとしているために発生している。
エラーメッセージは「BdsDxe: failed to start Boot0001 "UEFI QEMU DVD-ROM QM00005 " from PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x2,0xFFF,0x0): Time out」で、最後に「Time out」が出ているので間違いなさそう。
QEMUのコマンドを叩く直前にRemote Viewerを立ち上げておくと良い。
もしくは、UEFIの設定画面が立ち上がったあと、「Boot Maintenance Manager」→「」→「Boot From File」→「EFISECTOR,~~~~/CDROM(~~~」→「EFI」→「BOOT」→「BOOTX64.EFI」の順で選んでやるとDVDから起動できる。
UEFIの設定画面に入れない
物理PCでは、起動時に(メーカーによって異なるが)F2とかを押すと、UEFIの設定画面に入れるが、OVMFではできなかった。
代わりに、IPv4、IPv6でのPXEブートが失敗して、Shellが起動した後、ExitしてやるとUEFIの設定画面に入れる。解像度の設定もできるが、最初は設定されていないので、すごく小さな画面に表示される。解像度の設定は、次回起動時から有効になる。
追記:2022年8月13日
0 件のコメント:
コメントを投稿