OVMF: Difference between revisions
(add link to kraxel's qemu firmware repo) |
(update intro text to svn r14423, plus recommend Gerd's packaging primarily) |
||
Line 1: | Line 1: | ||
OVMF "is a project to enable UEFI support for Virtual Machines". This page tries to give yet another mini-howto about playing with OVMF boot firmware in qemu-kvm virtual machines plus libvirt, deferring heavily to the TianoCore upstream wiki. <em>Do</em> mercilessly edit any inaccuracies or wrong statements. | OVMF "is a project to enable UEFI support for Virtual Machines". This page tries to give yet another mini-howto about playing with OVMF boot firmware in qemu-kvm virtual machines plus libvirt, deferring heavily to the TianoCore upstream wiki. <em>Do</em> mercilessly edit any inaccuracies or wrong statements. | ||
This page is written as of edk2 svn rev | This page is written as of edk2 svn rev 14423 (virtio-blk, virtio-scsi and virtio-net are supported, and several guests can be booted with, and recognize secure boot). For using OVMF directly with the qemu command line, refer to the [https://github.com/tianocore/edk2/blob/master/OvmfPkg/README README]; this page tries to detail OVMF usage under (RHEL-6.4) libvirt. | ||
The recommended way for testing OVMF is installing Gerd Hoffman's RPM packages from his repo at http://www.kraxel.org/repos/, using yum. (The package to install is <code>edk2.git-ovmf-x64</code>; yum will pull in several dependencies from the repo.) The firmware images are located in the <code>/usr/share/edk2.git/ovmf-x64</code> directory. <code>OVMF-pure-efi.fd</code> is a "pure UEFI" image, while <code>OVMF-with-csm.fd</code> includes the Compatibility Support Module (CSM) build of SeaBIOS. <code>bios.bin</code> is a symlink to the latter. | |||
== Downloading the source == | == Downloading the source == |
Revision as of 06:02, 15 June 2013
OVMF "is a project to enable UEFI support for Virtual Machines". This page tries to give yet another mini-howto about playing with OVMF boot firmware in qemu-kvm virtual machines plus libvirt, deferring heavily to the TianoCore upstream wiki. Do mercilessly edit any inaccuracies or wrong statements.
This page is written as of edk2 svn rev 14423 (virtio-blk, virtio-scsi and virtio-net are supported, and several guests can be booted with, and recognize secure boot). For using OVMF directly with the qemu command line, refer to the README; this page tries to detail OVMF usage under (RHEL-6.4) libvirt.
The recommended way for testing OVMF is installing Gerd Hoffman's RPM packages from his repo at http://www.kraxel.org/repos/, using yum. (The package to install is edk2.git-ovmf-x64
; yum will pull in several dependencies from the repo.) The firmware images are located in the /usr/share/edk2.git/ovmf-x64
directory. OVMF-pure-efi.fd
is a "pure UEFI" image, while OVMF-with-csm.fd
includes the Compatibility Support Module (CSM) build of SeaBIOS. bios.bin
is a symlink to the latter.
Downloading the source
Clone either the main SVN repository (git svn recommended) or one of the git mirrors listed in the TianoCore wiki.
Building it
The EDK2 (EFI Development Kit 2) tree has a complex, but very portable and flexible build system, called BaseTools. OVMF is one of the sub-projects inside the EDK2 tree (located in the OvmfPkg subdirectory), relying on other modules inside the tree.
When building OVMF, the build system must be configured accordingly. Inter-module and intra-module dependencies are then handled automatically.
The build system's configuration is described in detail, rooted in this TianoCore wiki page.
Frequent rebuilds
For developers it is recommended to create a branch called base_config
or something similar off the master branch (in the git svn or plain git clone), capture the config steps described under the above edk2 upstream link in commits (including setting up a reasonable .gitignore
file), and keep rebasing base_config
after git svn rebase
/ git pull
commands. Fork/rebase your own development branches off/to base_config
.
One possible .gitignore
file is
*.d *.o *.pyc /BaseTools/Source/C/VfrCompile/EfiVfrParser.cpp /BaseTools/Source/C/VfrCompile/EfiVfrParser.h /BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr /BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg /BaseTools/Source/C/VfrCompile/VfrLexer.cpp /BaseTools/Source/C/VfrCompile/VfrLexer.h /BaseTools/Source/C/VfrCompile/VfrParser.dlg /BaseTools/Source/C/VfrCompile/VfrSyntax.cpp /BaseTools/Source/C/VfrCompile/VfrTokens.h /BaseTools/Source/C/bin/ /BaseTools/Source/C/libs/ /Build/ /Conf/.cache/
The very first time you build the tree, and after git clean -fdx
commands, you must (re)build BaseTools with make -C "$EDK_TOOLS_PATH"
. (You're going to have that variable set in your environment after sourcing edksetup.sh
in the root project dir; see the TianoCore Wiki again.)
One-off builds
Consult OvmfPkg/build.sh
and OvmfPkg/README
.
OvmfPkg/build.sh
takes care of BaseTools, configuration (according to command line options) and the main build. One potentially useful option is -n THREADNUMBER
, which enables parallel make. -D FLAG
options control optional build features/aspects; one place to look up the more common ones could be the SRPM / spec file here.
OvmfPkg/README
is slightly outdated; for example no separate OvmfVideo.rom
file is produced any longer.
Making guests use it
So now you have either downloaded a prebuilt binary, or installed the noarch RPM in the host, or built OVMF.fd
yourself. This "Flash Device" file is passed to qemu-kvm with the -bios
option (with full pathname), which is accessible in the libvirt domain XML as the /domain/os/loader
element.
Neither virt-manager
nor virt-install
seem to make this option readily configurable at guest installation time in RHEL-6.3. The following list of commands is one workaround. The EMULATOR
bit is elaborated upon under #qemu debug port.
# "configuration" NAME=set_guest_name_here INSTALL_ISO=/full/path/to/install/iso DRIVER_ISO=/full/path/to/virtio/driver/iso EMULATOR=/full/path/to/emulator LOADER=/full/path/to/OVMF.fd # create a domain XML template for guest installation: # - 4 VCPUs, 4G RAM # - virtio target disk, 25 GB in size # - first IDE CD-ROM has install disk # - second IDE CD-ROM has virtio driver disk # (should only be necessary for proprietary guests without built-in drivers) TARGET_DISK=/var/lib/libvirt/images/"$NAME".img virt-install \ --connect=qemu:///system \ --name=$NAME \ --ram=4096 \ --arch=x86_64 \ --machine=rhel6.3.0 \ --vcpus=4 \ --boot=cdrom,hd \ --disk=path=$TARGET_DISK,size=25,bus=virtio,format=qcow2 \ --disk=path=$DRIVER_ISO,device=cdrom,bus=ide,perms=ro,format=raw \ --disk=path=$INSTALL_ISO,device=cdrom,bus=ide,perms=ro,format=raw \ --print-step=1 \ | xmlstarlet ed -u /domain/devices/emulator -v $EMULATOR \ -s /domain/os -t elem -n loader -v $LOADER \ >template.xml # Import the template to libvirt virsh define template.xml # Now customize the guest further with "virsh edit" or inside virt-manager, # then start the installation.
For a virtio-scsi disk, apply the following changes:
- in the
TARGET_DISK
specification, replacebus=virtio
withbus=scsi
, - append the following options to the
xmlstarlet
command line:-s /domain/devices -t elem -n controller -v '' \ -s /domain/devices/controller -t attr -n type -v scsi \ -s /domain/devices/controller -t attr -n model -v virtio-scsi \
Saving OVMF debug messages
Debug log verbosity is controlled at build time. See the gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel
bitmask in OvmfPkg/OvmfPkgX64.dsc
. The individual bits (DEBUG_*
macros) are explained in MdePkg/Include/Library/DebugLib.h
.
serial console
Debug messages are written to the qemu debug port per default (see below), but they can be redirected to the (virtual) serial console with the -D DEBUG_ON_SERIAL_PORT
option at build time. In this case however the serial console will intermix framework debug messages with the TUI of the (U)EFI shell and other UEFI applications.
qemu debug port
This is where the debug messages are written by default, but capturing them on the host requires the -debugcon DEV -global isa-debugcon.iobase=0x402
qemu-kvm command line switches. These can be set on a guest-by-guest basis in the libvirt VM config XML files, using qemu:arg.
Alternatively, one might contemplate a qemu-kvm wrapper script like the following:
#!/bin/bash set -e -C -u NAME=0 for ARG in "$@"; do if [ x"$ARG" = x-name ]; then NAME=1 elif [ $NAME -ne 0 ]; then FNAME="${TMPDIR:-/tmp}/$ARG".debug exec /usr/libexec/qemu-kvm "$@" \ -debugcon file:"$FNAME" -global isa-debugcon.iobase=0x402 fi done exec /usr/libexec/qemu-kvm "$@"
The full path to the wrapper script is specified in the /domain/devices/emulator
element of the libvirt guest XML.
The script is adapted to the fact that libvirt invokes the emulator in two forms. XML validation after virsh edit
seems to invoke the emulator for verification purposes only, without the -name
option. In this case no debug file should be created / rewritten. When libvirt starts the guest, the -name
option is present, and the script constructs the logfile's name from the corresponding option-argument.
On an SELinux enabled system, the script's context should be set to that of the wrapped emulator, qemu-kvm. See chcon --reference
.
Furthermore, on an SELinux enabled system, a new instance of the same guest will be seclabelled differently from the previous instance, and will fail to overwrite the debug log produced by the previous instance. This could be worked around perhaps by reconfiguring libvirt's labelling practices for the guest, or changing the SELinux profile, or (horribile dictu) flipping SELinux to permissive. Removing the debug file manually before starting the next instance of the guest is simplest.
(Needless to say, never do any of this in production.)
Tested guest OS'en
Apparently working nicely
- Fedora 18 Alpha (XFCE edition). Secure boot tested as well.
- RHEL-6.3. (Its grub does not support booting from a virtio-blk disk. See #Making guests use it how to specify a virtio-scsi boot disk.)
- Windows 8 Consumer Preview Build 8250. Secure boot tested as well. The fix for qemu-kvm RHBZ#854304 may be necessary to run this guest. (Upstream qemu contains the fix of course.)
- Reportedly, Windows Server 2012.
Windows Server 2008 R2 SP1
This guest does not work correctly. Its UEFI installer is composed of several programs, some being UEFI applications, and the last layer being the Windows Pre-Installation Environment, running on the Windows 2008 R2 kernel.
The UEFI applications before the last layer correctly use the OVMF GOP (graphics output protocol), which drives the emulated Cirrus 5446 video card. Unfortunately, the last layer (WinPE) has a hard dependency on VGA BIOS interrupt 0x10, which is not provided by any OVMF CSM (compatibility support module) as of now.
This hard dependency is a Windows 2008 R2 bug; the WinPE layer should (actively) inherit the linear framebuffer characteristics from the GOP (UEFI boot phase), and use that until the kernel-level graphics drivers are loaded.
One (quite shabby) workaround for the time being is automated installation of this OS on top of OVMF, and then connecting to it with rdesktop
.
During most of the installation (ie. in the WinPE phase), nothing can be seen in the VNC window. The VM reboots several times, at which points cdboot.efi
shortly displays a (visible) message, "press a key to continue booting from the installation CD". No key should be pressed, as expected, but after the timeout, cdboot.efi
tends to crash, violating an edk2 framework ASSERT and falling into an infinite loop (watch the debug log).
If this happens, force off the VM, restart it, enter the OVMF setup utility, and manually set the on-hdd boot loader. The installation should resume then.
For the remote desktop connection, the IP address of the running guest can be fetched by searching /var/lib/libvirt/dnsmasq/default.leases
for the guest's MAC address (which is present in its libvirt XML file).
An example AutoUnattend.xml
file, and a corresponding guest XML template (to be used with virsh define
) are inserted below as a base-64 encoded, xz-compressed tarball. (Unfortunately, File Upload refuses xml and xml.gz files.) The install ISO that was augmented with the AutoUnattend.xml
file is named en_windows_server_2008_r2_with_sp1_x64_dvd_617601.iso
, its SHA1 is D3FD7BF85EE1D5BDD72DE5B2C69A7B470733CD0A
.
Note: the first ProductKey
element in the XML is a default key from
\SOURCES\PRODUCT.INI
. It does not participate in product
activation, it contributes to product selection at installation time.
begin-base64 600 example.tar.xz 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 ====
Confirmation of secure boot in Fedora 18
(This is a write-up of an earlier test.)
- I rebuilt OVMF with secure boot support.
- I downloaded the x86_64 binary RPM for pesign-0.10-5.fc18 and extracted the
/etc/pki/pesign
directory to$HOME/tmp/f18-keys
. - I extracted two certificates in DER format, standing in
$HOME/tmp
:certutil -L -d f18-keys -n 'Red Hat Test Certificate' -r \ >RedHatTestCertificate.der certutil -L -d f18-keys -n 'Red Hat Test CA' -r \ >RedHatTestCA.der
- I created a 64MB zero file,
- set up
/dev/loop1
on it, - created an MBR partition table with one 0x0c partition (cfdisk),
- (maybe ran
kpartx -a /dev/loop1
,) - formatted
/dev/mapper/loop1p1
as FAT32 with mkdosfs, - mounted it, created a directory called
Red Hat Secure Boot Keys
, - copied the output files from the previous step there.
- NOTE: libguestfs / guestfish is a much better way to do the same.
- I attached the above image file as second disk to my preexistent guest while it was shut down.
- I started the guest.
- As soon as the TianoCore splash screen showed, I entered the setup
menu and selected
Device Manager | Secure Boot Options
, - enrolled
RedHatTestCA.der
as PK. - enrolled
RedHatTestCertificate.der
as one KEK and one DB entry, - made sure
shim.efi
from the first disk was the first boot option inBoot Maintenance Manager | Boot Options
, - allowed the boot to continue.
-
shim.efi
printedBinary is whitelisted
. grub2 printedsecure boot forbids insmod
four times. The F18 XFCE GUI started. The guest dmesg contains[ 0.000000] Secure boot enabled
- OVMF secure boot configuration (enrolled keys etc) don't persist across guest shutdown (maybe not even across in-guest reboot); OVMF reverts to non-secure boot. Copying the certificates to the F18 boot partition didn't change this. What's more, when OVMF is built with Secure Boot support, even the boot order saved from last time is forgotten and default options are regenerated (even with no keys enrolled).
Confirmation of secure boot in Windows 8 Consumer Preview Build 8250
(This is also a write-up of an earlier test.)
Basically re-executed #Confirmation of secure boot in Fedora 18, with the following changes:
- I downloaded the platform key, the key exchange key, and three DB entries from James Bottomley's blog.
- Once inside the guest, I started PowerShell as an administrator and then verified that Secure Boot was enabled.