runqemu: support UEFI with OVMF firmware
In the simplest case, "runqemu qemux86 <some-image> qcow2 ovmf" for an EFI-enabled image in the qcow2 format will locate the ovmf.qcow2 firmware file deployed by the ovmf recipe in the image deploy directory, override the graphics hardware with "-vga std" because that is all that OVMF supports, and boot with UEFI enabled. ovmf is not built by default. Either do it explicitly ("bitbake ovmf") or make it a part of the normal build ("MACHINE_ESSENTIAL_EXTRA_RDEPENDS_append = ' ovmf'"). The firmware file is activated as a flash drive instead of using the qemu BIOS parameters, because that is the recommended method (https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=764918#47) as it allows storing UEFI variables in the file. Instead of just "ovmf", a full path to an existing file can also be used, just as with the rootfs. That may be useful when making a permanent copy of the virtual machine data files. It is possible to specify "ovmf*" parameters more than once, then each parameter creates a separate flash drive. This way it is possible to use separate flash drives for firmware code and variables: $ runqemu qemux86 <some-image> qcow2 ovmf.code ovmf.vars" Note that rebuilding ovmf will overwrite the ovmf.vars.qcow2 file in the image deploy directory. So when the goal is to update the firmware while keeping variables, make a copy of the variable file and use that: $ mkdir my-machine $ cp tmp/deploy/images/qemux86/ovmf.vars.qcow2 my-machine/ $ runqemu qemux86 <some-image> qcow2 ovmf.code my-machine/ovmf.vars.qcow2 When Secure Boot was enabled in ovmf, one can pick that instead of the non-Secure-Boot enabled ovmf.code: $ runqemu qemux86 <some-image> qcow2 ovmf.secboot.code my-machine/ovmf.vars.qcow2 (From OE-Core rev: b91fc0893651b9e3069893e36439de0b4e70ad13) Signed-off-by: Patrick Ohly <patrick.ohly@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
parent
63f61a1aff
commit
715f4e3ec1
|
@ -74,6 +74,7 @@ of the following environment variables (in any order):
|
||||||
kvm-vhost - enable KVM with vhost when running x86/x86_64 (VT-capable CPU required)
|
kvm-vhost - enable KVM with vhost when running x86/x86_64 (VT-capable CPU required)
|
||||||
publicvnc - enable a VNC server open to all hosts
|
publicvnc - enable a VNC server open to all hosts
|
||||||
audio - enable audio
|
audio - enable audio
|
||||||
|
[*/]ovmf* - OVMF firmware file or base name for booting with UEFI
|
||||||
tcpserial=<port> - specify tcp serial port number
|
tcpserial=<port> - specify tcp serial port number
|
||||||
biosdir=<dir> - specify custom bios dir
|
biosdir=<dir> - specify custom bios dir
|
||||||
biosfilename=<filename> - specify bios filename
|
biosfilename=<filename> - specify bios filename
|
||||||
|
@ -175,6 +176,13 @@ class BaseConfig(object):
|
||||||
self.clean_nfs_dir = False
|
self.clean_nfs_dir = False
|
||||||
self.nfs_server = ''
|
self.nfs_server = ''
|
||||||
self.rootfs = ''
|
self.rootfs = ''
|
||||||
|
# File name(s) of a OVMF firmware file or variable store,
|
||||||
|
# to be added with -drive if=pflash.
|
||||||
|
# Found in the same places as the rootfs, with or without one of
|
||||||
|
# these suffices: qcow2, bin.
|
||||||
|
# Setting one also adds "-vga std" because that is all that
|
||||||
|
# OVMF supports.
|
||||||
|
self.ovmf_bios = []
|
||||||
self.qemuboot = ''
|
self.qemuboot = ''
|
||||||
self.qbconfload = False
|
self.qbconfload = False
|
||||||
self.kernel = ''
|
self.kernel = ''
|
||||||
|
@ -281,6 +289,7 @@ class BaseConfig(object):
|
||||||
- Check whether is a kernel file
|
- Check whether is a kernel file
|
||||||
- Check whether is a image file
|
- Check whether is a image file
|
||||||
- Check whether it is a nfs dir
|
- Check whether it is a nfs dir
|
||||||
|
- Check whether it is a OVMF flash file
|
||||||
"""
|
"""
|
||||||
if p.endswith('.qemuboot.conf'):
|
if p.endswith('.qemuboot.conf'):
|
||||||
self.qemuboot = p
|
self.qemuboot = p
|
||||||
|
@ -321,6 +330,8 @@ class BaseConfig(object):
|
||||||
else:
|
else:
|
||||||
logger.info("Assuming %s is an nfs rootfs" % p)
|
logger.info("Assuming %s is an nfs rootfs" % p)
|
||||||
self.check_arg_nfs(p)
|
self.check_arg_nfs(p)
|
||||||
|
elif os.path.basename(p).startswith('ovmf'):
|
||||||
|
self.ovmf_bios.append(p)
|
||||||
else:
|
else:
|
||||||
raise Exception("Unknown path arg %s" % p)
|
raise Exception("Unknown path arg %s" % p)
|
||||||
|
|
||||||
|
@ -406,6 +417,8 @@ class BaseConfig(object):
|
||||||
elif re.search(r'-image-|-image$', arg):
|
elif re.search(r'-image-|-image$', arg):
|
||||||
# Lazy rootfs
|
# Lazy rootfs
|
||||||
self.rootfs = arg
|
self.rootfs = arg
|
||||||
|
elif arg.startswith('ovmf'):
|
||||||
|
self.ovmf_bios.append(arg)
|
||||||
else:
|
else:
|
||||||
# At last, assume is it the MACHINE
|
# At last, assume is it the MACHINE
|
||||||
if (not unknown_arg) or unknown_arg == arg:
|
if (not unknown_arg) or unknown_arg == arg:
|
||||||
|
@ -504,6 +517,20 @@ class BaseConfig(object):
|
||||||
if not os.path.exists(self.rootfs):
|
if not os.path.exists(self.rootfs):
|
||||||
raise Exception("Can't find rootfs: %s" % self.rootfs)
|
raise Exception("Can't find rootfs: %s" % self.rootfs)
|
||||||
|
|
||||||
|
def check_ovmf(self):
|
||||||
|
"""Check and set full path for OVMF firmware and variable file(s)."""
|
||||||
|
|
||||||
|
for index, ovmf in enumerate(self.ovmf_bios):
|
||||||
|
if os.path.exists(ovmf):
|
||||||
|
continue
|
||||||
|
for suffix in ('qcow2', 'bin'):
|
||||||
|
path = '%s/%s.%s' % (self.get('DEPLOY_DIR_IMAGE'), ovmf, suffix)
|
||||||
|
if os.path.exists(path):
|
||||||
|
self.ovmf_bios[index] = path
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
raise Exception("Can't find OVMF firmware: %s" % ovmf)
|
||||||
|
|
||||||
def check_kernel(self):
|
def check_kernel(self):
|
||||||
"""Check and set kernel, dtb"""
|
"""Check and set kernel, dtb"""
|
||||||
# The vm image doesn't need a kernel
|
# The vm image doesn't need a kernel
|
||||||
|
@ -598,6 +625,7 @@ class BaseConfig(object):
|
||||||
self.check_kvm()
|
self.check_kvm()
|
||||||
self.check_fstype()
|
self.check_fstype()
|
||||||
self.check_rootfs()
|
self.check_rootfs()
|
||||||
|
self.check_ovmf()
|
||||||
self.check_kernel()
|
self.check_kernel()
|
||||||
self.check_biosdir()
|
self.check_biosdir()
|
||||||
self.check_mem()
|
self.check_mem()
|
||||||
|
@ -706,6 +734,8 @@ class BaseConfig(object):
|
||||||
print('NFS_DIR: [%s]' % self.nfs_dir)
|
print('NFS_DIR: [%s]' % self.nfs_dir)
|
||||||
else:
|
else:
|
||||||
print('ROOTFS: [%s]' % self.rootfs)
|
print('ROOTFS: [%s]' % self.rootfs)
|
||||||
|
if self.ovmf_bios:
|
||||||
|
print('OVMF: %s' % self.ovmf_bios)
|
||||||
print('CONFFILE: [%s]' % self.qemuboot)
|
print('CONFFILE: [%s]' % self.qemuboot)
|
||||||
print('')
|
print('')
|
||||||
|
|
||||||
|
@ -1012,7 +1042,17 @@ class BaseConfig(object):
|
||||||
|
|
||||||
check_libgl(qemu_bin)
|
check_libgl(qemu_bin)
|
||||||
|
|
||||||
self.qemu_opt = "%s %s %s %s %s" % (qemu_bin, self.get('NETWORK_CMD'), self.get('ROOTFS_OPTIONS'), self.get('QB_OPT_APPEND'), self.qemu_opt_script)
|
self.qemu_opt = "%s %s %s %s" % (qemu_bin, self.get('NETWORK_CMD'), self.get('ROOTFS_OPTIONS'), self.get('QB_OPT_APPEND'))
|
||||||
|
|
||||||
|
for ovmf in self.ovmf_bios:
|
||||||
|
format = ovmf.rsplit('.', 1)[-1]
|
||||||
|
self.qemu_opt += ' -drive if=pflash,format=%s,file=%s' % (format, ovmf)
|
||||||
|
if self.ovmf_bios:
|
||||||
|
# OVMF only supports normal VGA, i.e. we need to override a -vga vmware
|
||||||
|
# that gets added for example for normal qemux86.
|
||||||
|
self.qemu_opt += ' -vga std'
|
||||||
|
|
||||||
|
self.qemu_opt += ' ' + self.qemu_opt_script
|
||||||
|
|
||||||
if self.snapshot:
|
if self.snapshot:
|
||||||
self.qemu_opt += " -snapshot"
|
self.qemu_opt += " -snapshot"
|
||||||
|
|
Loading…
Reference in New Issue